diff --git a/.qoder/repowiki/zh/content/API参考/API参考.md b/.qoder/repowiki/zh/content/API参考/API参考.md index f3e4a38..f5798b2 100644 --- a/.qoder/repowiki/zh/content/API参考/API参考.md +++ b/.qoder/repowiki/zh/content/API参考/API参考.md @@ -11,6 +11,7 @@ ## 目录 + 1. [简介](#简介) 2. [API认证与签名机制](#api认证与签名机制) 3. [支付下单接口](#支付下单接口) @@ -21,24 +22,30 @@ 8. [常见错误码与解决方案](#常见错误码与解决方案) ## 简介 -本文档为kami_gateway系统的公开RESTful API提供完整的技术参考。文档基于`router.go`中的路由定义,系统性地描述了支付下单、订单查询和回调通知三大核心流程的接口规范。所有请求和响应结构均引用`internal/schema/request`和`internal/schema/response`中的定义。本文档还详细说明了API的签名验证机制、安全要求,并提供实际使用示例。 + +本文档为kami_gateway系统的公开RESTful API提供完整的技术参考。文档基于`router.go` +中的路由定义,系统性地描述了支付下单、订单查询和回调通知三大核心流程的接口规范。所有请求和响应结构均引用 +`internal/schema/request`和`internal/schema/response`中的定义。本文档还详细说明了API的签名验证机制、安全要求,并提供实际使用示例。 ## API认证与签名机制 -所有API请求必须通过签名验证以确保安全性和完整性。签名算法基于MD5,具体实现位于`sign_verify.go`中。不同接口可能使用不同的签名方法,主要分为标准MD5签名和MF格式签名。 +所有API请求必须通过签名验证以确保安全性和完整性。签名算法基于MD5,具体实现位于`sign_verify.go` +中。不同接口可能使用不同的签名方法,主要分为标准MD5签名和MF格式签名。 ### 签名生成规则 + 1. **标准MD5签名(GetMD5Sign)**: - - 将所有非空参数按键名的字母顺序排序 - - 拼接格式为:`key1=value1&key2=value2&...&paySecret=商户密钥` - - 对拼接后的字符串进行MD5加密,并转换为大写 + - 将所有非空参数按键名的字母顺序排序 + - 拼接格式为:`key1=value1&key2=value2&...&paySecret=商户密钥` + - 对拼接后的字符串进行MD5加密,并转换为大写 2. **MF格式签名(GetMD5SignMF)**: - - 将所有非空参数按键名的字母顺序排序 - - 拼接格式为:`key1value1key2value2...paySecret` - - 对拼接后的字符串进行MD5加密,并转换为小写 + - 将所有非空参数按键名的字母顺序排序 + - 拼接格式为:`key1value1key2value2...paySecret` + - 对拼接后的字符串进行MD5加密,并转换为小写 ### 签名验证流程 + 1. 服务端接收到请求后,提取`sign`参数 2. 根据接口类型选择相应的签名算法 3. 使用商户密钥重新计算签名 @@ -46,6 +53,7 @@ 5. 签名验证失败将返回错误响应 **Section sources** + - [sign_verify.go](file://internal/utils/sign_verify.go#L1-L104) ## 支付下单接口 @@ -53,33 +61,38 @@ 支付下单接口用于创建新的支付订单,是支付流程的起点。 ### 接口定义 + - **HTTP方法**:POST - **URL模式**:`/gateway/scan` - **认证方式**:MD5签名 ### 请求头 -| 头部字段 | 是否必需 | 描述 | -|---------|--------|------| -| Content-Type | 是 | 必须为 `application/json` | + +| 头部字段 | 是否必需 | 描述 | +|--------------|------|------------------------| +| Content-Type | 是 | 必须为 `application/json` | ### 请求体(Schema: CreatedOrder) + 请求体结构定义在`internal/schema/request/order.go`中,具体字段如下: -| 字段名 | 类型 | 是否必需 | 描述 | -|-------|------|--------|------| -| payKey | string | 是 | 商户唯一标识key,由系统分配 | -| orderNo | string | 是 | 商户侧订单号,需保证唯一性 | -| orderPrice | float64 | 是 | 订单金额,单位为元 | -| orderPeriod | int | 否 | 订单周期(天) | -| notifyUrl | string | 是 | 支付成功后的回调通知地址 | -| sign | string | 是 | 签名字符串,用于验证请求合法性 | -| productCode | string | 是 | 产品编码,标识支付产品类型 | -| timestamp | int64 | 是 | 时间戳,单位为毫秒 | +| 字段名 | 类型 | 是否必需 | 描述 | +|-------------|---------|------|-----------------| +| payKey | string | 是 | 商户唯一标识key,由系统分配 | +| orderNo | string | 是 | 商户侧订单号,需保证唯一性 | +| orderPrice | float64 | 是 | 订单金额,单位为元 | +| orderPeriod | int | 否 | 订单周期(天) | +| notifyUrl | string | 是 | 支付成功后的回调通知地址 | +| sign | string | 是 | 签名字符串,用于验证请求合法性 | +| productCode | string | 是 | 产品编码,标识支付产品类型 | +| timestamp | int64 | 是 | 时间戳,单位为毫秒 | ### 响应体 + 成功响应返回`ScanSuccessData`结构,失败返回`ScanFailData`结构。 #### 成功响应示例 + ```json { "orderNo": "ORD20231101001", @@ -93,6 +106,7 @@ ``` #### 失败响应示例 + ```json { "payKey": "MCH123456", @@ -103,6 +117,7 @@ ``` **Section sources** + - [router.go](file://internal/routers/router.go#L1-L75) - [order.go](file://internal/schema/request/order.go#L1-L35) - [pay_resp.go](file://internal/schema/response/pay_resp.go#L1-L38) @@ -113,32 +128,36 @@ 订单查询接口允许商户查询已创建订单的状态和详细信息。 ### 接口定义 + - **HTTP方法**:GET - **URL模式**:`/gateway/merchant/query` - **认证方式**:MF格式MD5签名 ### 请求参数 -| 参数名 | 类型 | 是否必需 | 描述 | -|-------|------|--------|------| -| appKey | string | 是 | 商户应用key,用于身份识别 | -| orderNo | string | 是 | 商户侧订单号 | -| timestamp | string | 是 | 请求时间戳,格式为Unix时间戳字符串 | -| sign | string | 是 | MF格式签名 | + +| 参数名 | 类型 | 是否必需 | 描述 | +|-----------|--------|------|---------------------| +| appKey | string | 是 | 商户应用key,用于身份识别 | +| orderNo | string | 是 | 商户侧订单号 | +| timestamp | string | 是 | 请求时间戳,格式为Unix时间戳字符串 | +| sign | string | 是 | MF格式签名 | ### 响应体(Schema: OrderQueryResp) + 响应体结构定义在`internal/schema/response`中,包含订单的完整状态信息。 -| 字段名 | 类型 | 描述 | -|-------|------|------| -| orderNo | string | 系统生成的订单号 | -| cardNo | string | 卡号(如适用) | -| cardPwd | string | 卡密(如适用) | -| status | string | 订单状态:`wait`(等待)、`success`(成功)、`fail`(失败) | -| faceVal | float64 | 实际面值金额 | -| cardReturnData | string | 通道返回的原始数据 | -| amount | string | 显示金额,格式化为字符串 | +| 字段名 | 类型 | 描述 | +|----------------|---------|------------------------------------------| +| orderNo | string | 系统生成的订单号 | +| cardNo | string | 卡号(如适用) | +| cardPwd | string | 卡密(如适用) | +| status | string | 订单状态:`wait`(等待)、`success`(成功)、`fail`(失败) | +| faceVal | float64 | 实际面值金额 | +| cardReturnData | string | 通道返回的原始数据 | +| amount | string | 显示金额,格式化为字符串 | ### 成功响应示例 + ```json { "code": 0, @@ -156,6 +175,7 @@ ``` ### 错误响应示例 + ```json { "code": -1, @@ -164,6 +184,7 @@ ``` **Section sources** + - [router.go](file://internal/routers/router.go#L1-L75) - [order_controller.go](file://internal/controllers/order_controller.go#L1-L226) @@ -172,24 +193,28 @@ 回调通知接口用于接收第三方支付平台的支付结果通知,是支付流程的终点。 ### 接口定义 + - **HTTP方法**:POST - **URL模式**:`/gateway/supplier/order/query` - **认证方式**:无(由第三方系统调用) ### 请求参数 -| 参数名 | 类型 | 是否必需 | 描述 | -|-------|------|--------|------| -| bankOrderId | string | 是 | 系统内部订单号 | + +| 参数名 | 类型 | 是否必需 | 描述 | +|-------------|--------|------|---------| +| bankOrderId | string | 是 | 系统内部订单号 | ### 响应格式 + 接口返回纯文本响应,用于确认接收状态。 -| 状态 | 响应内容 | -|------|----------| +| 状态 | 响应内容 | +|----|-----------| | 成功 | "success" | -| 失败 | 错误描述信息 | +| 失败 | 错误描述信息 | ### 处理流程 + 1. 系统接收到第三方通知 2. 根据`bankOrderId`查询订单信息 3. 更新订单状态为成功 @@ -209,6 +234,7 @@ Gateway-->>ThirdParty : "success" ``` **Diagram sources** + - [router.go](file://internal/routers/router.go#L1-L75) - [order_controller.go](file://internal/controllers/order_controller.go#L1-L226) @@ -217,6 +243,7 @@ Gateway-->>ThirdParty : "success" 代付接口用于处理商户的代付请求,包括代付下单、余额查询和结果查询。 ### 接口列表 + - **代付下单**:`/gateway/payfor` (当前注释状态) - **代付查询**:`/gateway/payfor/query` (当前注释状态) - **余额查询**:`/gateway/balance` (当前注释状态) @@ -226,11 +253,13 @@ Gateway-->>ThirdParty : "success" > **注意**:根据`router.go`中的代码,大部分代付接口当前处于注释状态,表示功能尚未启用或正在开发中。 **Section sources** + - [router.go](file://internal/routers/router.go#L1-L75) ## 客户端调用示例 ### Go语言调用示例 + ```go package main @@ -316,19 +345,21 @@ func main() { ``` **Section sources** + - [order.go](file://internal/schema/request/order.go#L1-L35) ## 常见错误码与解决方案 -| 错误码 | 错误信息 | 可能原因 | 解决方案 | -|-------|--------|--------|--------| -| -1 | 参数错误 | 必填参数缺失或格式不正确 | 检查所有必需参数是否完整且格式正确 | -| -1 | key错误 | appKey或payKey无效 | 确认使用的key是否正确且已激活 | -| -1 | 签名错误 | 签名计算不正确 | 严格按照签名规则重新计算签名,注意参数排序和拼接方式 | -| -1 | 订单不存在 | 查询的订单号不存在 | 确认订单号是否正确,或检查是否已成功创建订单 | -| 400 | 参数验证失败 | 请求参数不符合验证规则 | 检查参数类型、长度和格式是否符合API文档要求 | -| 500 | 内部错误 | 服务器内部处理异常 | 联系技术支持,提供请求时间、订单号等信息 | +| 错误码 | 错误信息 | 可能原因 | 解决方案 | +|-----|--------|-----------------|----------------------------| +| -1 | 参数错误 | 必填参数缺失或格式不正确 | 检查所有必需参数是否完整且格式正确 | +| -1 | key错误 | appKey或payKey无效 | 确认使用的key是否正确且已激活 | +| -1 | 签名错误 | 签名计算不正确 | 严格按照签名规则重新计算签名,注意参数排序和拼接方式 | +| -1 | 订单不存在 | 查询的订单号不存在 | 确认订单号是否正确,或检查是否已成功创建订单 | +| 400 | 参数验证失败 | 请求参数不符合验证规则 | 检查参数类型、长度和格式是否符合API文档要求 | +| 500 | 内部错误 | 服务器内部处理异常 | 联系技术支持,提供请求时间、订单号等信息 | **Section sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L1-L226) - [pay_resp.go](file://internal/schema/response/pay_resp.go#L1-L38) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/API参考/代付API.md b/.qoder/repowiki/zh/content/API参考/代付API.md index 1cd686f..a31b6dd 100644 --- a/.qoder/repowiki/zh/content/API参考/代付API.md +++ b/.qoder/repowiki/zh/content/API参考/代付API.md @@ -11,6 +11,7 @@ ## 目录 + 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) @@ -22,9 +23,11 @@ 9. [结论](#结论) ## 简介 + 本文档旨在为kami_gateway系统的代付功能创建全面的API文档。尽管相关控制器代码被注释,但基于现有代码结构和命名约定,详细说明了代付API的设计意图和预期功能。文档涵盖了代付请求、结果查询、余额查询以及手动处理代付结果等关键端点,解释了代付流程中的核心参数、签名验证机制和参数校验逻辑。 ## 项目结构 + kami_gateway项目采用分层架构设计,主要分为conf、deploy、internal三大目录。代付功能的核心代码位于internal目录下,包括controllers、service、models、schema等子模块。这种结构实现了关注点分离,便于维护和扩展。 ```mermaid @@ -48,23 +51,28 @@ deploy --> internal ``` **图示来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) - [router.go](file://internal/routers/router.go) **本节来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) - [router.go](file://internal/routers/router.go) ## 核心组件 + 代付功能的核心组件包括PayForGateway控制器、pay_for服务、PayforInfo模型和相关响应结构体。这些组件协同工作,处理代付请求的接收、验证、处理和结果返回。控制器负责接收HTTP请求,服务层处理业务逻辑,模型定义数据结构,响应结构体规范API输出格式。 **本节来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_info.go](file://internal/models/payfor/payfor_info.go) - [payfor_resp.go](file://internal/schema/response/payfor_resp.go) ## 架构概述 + 代付功能的架构采用典型的MVC模式,通过控制器接收请求,调用服务层处理业务逻辑,操作模型层的数据,并返回标准化的响应。整个流程涉及签名验证、参数校验、数据库操作和事务管理,确保了代付操作的安全性和一致性。 ```mermaid @@ -81,6 +89,7 @@ Controller --> Client ``` **图示来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go#L7-L7) - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_info.go](file://internal/models/payfor/payfor_info.go) @@ -88,9 +97,11 @@ Controller --> Client ## 详细组件分析 ### 代付网关控制器分析 + PayForGateway控制器是代付功能的入口点,继承自web.Controller,提供了多个代付相关的API端点。尽管这些方法被注释,但其设计意图清晰,涵盖了代付请求、结果查询、余额查询和手动结果处理等完整流程。 #### 控制器结构 + ```mermaid classDiagram class PayForGateway { @@ -105,9 +116,11 @@ PayForGateway --> web.Controller : "继承" ``` **图示来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go#L7-L7) #### API端点流程 + ```mermaid flowchart TD Start([接收请求]) --> ValidateParams["验证参数完整性"] @@ -124,16 +137,20 @@ ReturnAuthError --> End ``` **图示来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) **本节来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) ### 代付服务分析 + pay_for服务模块实现了代付功能的核心业务逻辑,包括自动代付、结果查询和余额查询等功能。服务层与模型层紧密协作,确保数据的一致性和完整性。 #### 服务功能关系 + ```mermaid classDiagram class PayForResultQuery { @@ -156,16 +173,20 @@ BalanceQuery --> GetMD5Sign : "调用" ``` **图示来源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) **本节来源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) ### 代付信息模型分析 + PayforInfo模型定义了代付记录的数据结构,包含代付交易的完整信息,从商户信息到银行账户详情,再到交易状态和金额明细。 #### 数据模型结构 + ```mermaid classDiagram class PayforInfo { @@ -199,15 +220,19 @@ PayforInfo <|-- PayforInfoMethods : "实现" ``` **图示来源** + - [payfor_info.go](file://internal/models/payfor/payfor_info.go) **本节来源** + - [payfor_info.go](file://internal/models/payfor/payfor_info.go) ### 响应结构分析 + 响应结构体定义了API的输出格式,确保了前后端交互的一致性和可预测性。不同的代付操作返回不同但结构相似的响应。 #### 响应结构关系 + ```mermaid classDiagram class PayForResponse { @@ -240,12 +265,15 @@ class BalanceResponse { ``` **图示来源** + - [payfor_resp.go](file://internal/schema/response/payfor_resp.go) **本节来源** + - [payfor_resp.go](file://internal/schema/response/payfor_resp.go) ## 依赖分析 + 代付功能依赖于多个内部模块和外部服务,形成了复杂的依赖网络。理解这些依赖关系对于维护和扩展系统至关重要。 ```mermaid @@ -262,27 +290,33 @@ PayForSolve --> AccountModel ``` **图示来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) - [router.go](file://internal/routers/router.go) **本节来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) - [router.go](file://internal/routers/router.go) ## 性能考虑 + 代付功能在设计时考虑了性能和可靠性。通过使用数据库事务确保数据一致性,采用签名验证机制保障安全性,并通过合理的错误处理提高系统的健壮性。尽管功能被注释,但其设计体现了对高并发场景下性能和一致性的考量。 ## 故障排除指南 + 当代付功能出现问题时,应首先检查日志输出,重点关注签名验证失败、参数校验错误和数据库操作异常。由于相关路由被注释,需要确认是否已正确启用代付功能。同时,检查商户配置和通道设置是否正确,确保代付流程所需的各项条件都已满足。 **本节来源** + - [payfor_controller.go](file://internal/controllers/payfor_controller.go) - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) ## 结论 + 尽管kami_gateway的代付功能当前被注释,但其代码结构清晰,设计完整。系统提供了从代付请求到结果处理的全流程支持,包括自动代付、结果查询、余额查询和手动结果修正等关键功能。通过详细的API文档和清晰的代码结构,为未来启用和维护代付功能奠定了坚实基础。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/API参考/回调API.md b/.qoder/repowiki/zh/content/API参考/回调API.md index 692d2d6..c791b76 100644 --- a/.qoder/repowiki/zh/content/API参考/回调API.md +++ b/.qoder/repowiki/zh/content/API参考/回调API.md @@ -9,6 +9,7 @@ ## 目录 + 1. [回调API](#回调api) 2. [核心组件](#核心组件) 3. [处理流程](#处理流程) @@ -18,22 +19,31 @@ ## 回调API -kami_gateway系统通过一系列回调API端点接收来自不同第三方支付渠道的支付结果通知。这些端点包括`/mfcard/notifyV2`、`/appleCard/notify`、`/tMallGame/notify`等,每个端点对应一个特定的支付渠道,如爱博、京东卡、天猫游戏等。当支付渠道完成交易后,会向这些预设的URL发送HTTP请求,携带支付结果信息,从而触发网关内部的订单状态更新流程。 +kami_gateway系统通过一系列回调API端点接收来自不同第三方支付渠道的支付结果通知。这些端点包括`/mfcard/notifyV2`、 +`/appleCard/notify`、`/tMallGame/notify` +等,每个端点对应一个特定的支付渠道,如爱博、京东卡、天猫游戏等。当支付渠道完成交易后,会向这些预设的URL发送HTTP请求,携带支付结果信息,从而触发网关内部的订单状态更新流程。 -这些回调接口由`internal/routers/router.go`文件中的路由配置定义,将不同的URL路径映射到对应的实现结构体(如`MFCardV2Impl`、`AppleCardImpl`、`TMAllGameImpl`)的`PayNotify`方法上。整个回调系统的设计旨在确保支付结果的最终一致性,通过验证、处理和状态更新等一系列操作,保证商户和平台的账务准确无误。 +这些回调接口由`internal/routers/router.go`文件中的路由配置定义,将不同的URL路径映射到对应的实现结构体(如`MFCardV2Impl`、 +`AppleCardImpl`、`TMAllGameImpl`)的`PayNotify`方法上。整个回调系统的设计旨在确保支付结果的最终一致性,通过验证、处理和状态更新等一系列操作,保证商户和平台的账务准确无误。 **Section sources** + - [router.go](file://internal/routers/router.go#L49-L74) ## 核心组件 回调API的核心处理逻辑由三个关键组件构成:路由控制器、支付渠道实现和订单解决服务。 -首先,`internal/routers/router.go`文件定义了所有回调端点的路由规则。例如,`web.Router("/mfcard/notifyV2", &third_party.MFCardV2Impl{}, "*:PayNotify")`这一行代码将`/mfcard/notifyV2`路径的请求路由到`MFCardV2Impl`结构体的`PayNotify`方法。这为每个支付渠道提供了独立的入口。 +首先,`internal/routers/router.go`文件定义了所有回调端点的路由规则。例如, +`web.Router("/mfcard/notifyV2", &third_party.MFCardV2Impl{}, "*:PayNotify")`这一行代码将`/mfcard/notifyV2`路径的请求路由到 +`MFCardV2Impl`结构体的`PayNotify`方法。这为每个支付渠道提供了独立的入口。 -其次,各个支付渠道的处理逻辑封装在`internal/service/supplier/third_party/`目录下的具体实现中。`MFCardV2Impl`、`AppleCardImpl`和`TMAllGameImpl`等结构体都嵌入了`web.Controller`,并实现了`PayNotify`方法。这些方法负责接收、解析和验证来自不同渠道的回调数据。 +其次,各个支付渠道的处理逻辑封装在`internal/service/supplier/third_party/`目录下的具体实现中。`MFCardV2Impl`、 +`AppleCardImpl`和`TMAllGameImpl`等结构体都嵌入了`web.Controller`,并实现了`PayNotify`方法。这些方法负责接收、解析和验证来自不同渠道的回调数据。 -最后,`SolvePaySuccess`和`SolvePayFail`函数是订单状态更新的核心。它们位于`internal/service/pay_solve.go`文件中,被所有`PayNotify`方法调用。`SolvePaySuccess`在支付成功时执行,负责更新订单状态为成功、增加商户账户余额、记录动账历史和更新通道统计数据。`SolvePayFail`则在支付失败时调用,将订单状态标记为失败,并记录失败原因。 +最后,`SolvePaySuccess`和`SolvePayFail`函数是订单状态更新的核心。它们位于`internal/service/pay_solve.go`文件中,被所有 +`PayNotify`方法调用。`SolvePaySuccess`在支付成功时执行,负责更新订单状态为成功、增加商户账户余额、记录动账历史和更新通道统计数据。 +`SolvePayFail`则在支付失败时调用,将订单状态标记为失败,并记录失败原因。 ```mermaid classDiagram @@ -56,6 +66,7 @@ TMAllGameImpl --> PaySolveService : "调用" ``` **Diagram sources** + - [router.go](file://internal/routers/router.go#L49-L74) - [pay_solve.go](file://internal/service/pay_solve.go#L37-L254) - [mf178_v2.go](file://internal/service/supplier/third_party/mf178_v2.go#L187-L253) @@ -63,6 +74,7 @@ TMAllGameImpl --> PaySolveService : "调用" - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L167-L223) **Section sources** + - [pay_solve.go](file://internal/service/pay_solve.go#L37-L254) - [mf178_v2.go](file://internal/service/supplier/third_party/mf178_v2.go#L37-L39) - [apple.go](file://internal/service/supplier/third_party/apple.go#L33-L35) @@ -72,13 +84,19 @@ TMAllGameImpl --> PaySolveService : "调用" 回调API的处理流程是一个严谨的、多步骤的验证和更新过程,确保了数据的完整性和业务逻辑的正确性。 -1. **接收与查找**:当一个回调请求到达时,其`PayNotify`方法首先从请求参数中提取出订单号(如`attach`或`merchantOrder`)。然后,系统调用`order.GetOrderByBankOrderId(ctx, orderNo)`来根据这个订单号从数据库中查找对应的订单信息。如果订单不存在,系统会立即终止处理并返回失败响应。 +1. **接收与查找**:当一个回调请求到达时,其`PayNotify`方法首先从请求参数中提取出订单号(如`attach`或`merchantOrder` + )。然后,系统调用`order.GetOrderByBankOrderId(ctx, orderNo)`来根据这个订单号从数据库中查找对应的订单信息。如果订单不存在,系统会立即终止处理并返回失败响应。 -2. **验证与完整性检查**:在确认订单存在后,系统会进行一系列验证。这包括检查支付通道是否有效(通过`road.GetRoadInfoByRoadUid`),以及验证回调数据的签名。例如,`MFCardV2Impl`使用`utils.GetMD5SignMF`函数根据预设的密钥重新计算签名,并与回调中的`sign`参数进行比对。如果签名不匹配,处理将被终止。 +2. **验证与完整性检查**:在确认订单存在后,系统会进行一系列验证。这包括检查支付通道是否有效(通过`road.GetRoadInfoByRoadUid` + ),以及验证回调数据的签名。例如,`MFCardV2Impl`使用`utils.GetMD5SignMF`函数根据预设的密钥重新计算签名,并与回调中的`sign` + 参数进行比对。如果签名不匹配,处理将被终止。 -3. **状态判断与解决**:一旦数据通过验证,系统会根据回调中的状态码来决定后续操作。以`MFCardV2Impl`为例,当`status`为`"9"`时,系统会调用`service.SolvePaySuccess`;当`status`为`"8"`时,则调用`service.SolvePayFail`。`SolvePaySuccess`函数在一个数据库事务中执行,确保了所有相关操作(更新订单、更新账户、插入动账记录等)的原子性。 +3. **状态判断与解决**:一旦数据通过验证,系统会根据回调中的状态码来决定后续操作。以`MFCardV2Impl`为例,当`status`为`"9"` + 时,系统会调用`service.SolvePaySuccess`;当`status`为`"8"`时,则调用`service.SolvePayFail`。`SolvePaySuccess` + 函数在一个数据库事务中执行,确保了所有相关操作(更新订单、更新账户、插入动账记录等)的原子性。 -4. **响应返回**:处理完成后,系统会向支付渠道返回一个响应。通常,处理成功时返回`"SUCCESS"`,失败时返回`"FAIL"`。这个响应告诉支付渠道网关是否成功接收并处理了通知。 +4. **响应返回**:处理完成后,系统会向支付渠道返回一个响应。通常,处理成功时返回`"SUCCESS"`,失败时返回`"FAIL"` + 。这个响应告诉支付渠道网关是否成功接收并处理了通知。 ```mermaid flowchart TD @@ -100,12 +118,14 @@ M --> N[结束] ``` **Diagram sources** + - [mf178_v2.go](file://internal/service/supplier/third_party/mf178_v2.go#L187-L253) - [apple.go](file://internal/service/supplier/third_party/apple.go#L202-L240) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L167-L223) - [pay_solve.go](file://internal/service/pay_solve.go#L37-L254) **Section sources** + - [mf178_v2.go](file://internal/service/supplier/third_party/mf178_v2.go#L187-L253) - [apple.go](file://internal/service/supplier/third_party/apple.go#L202-L240) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L167-L223) @@ -115,18 +135,22 @@ M --> N[结束] 尽管各个支付渠道的回调接口各不相同,但它们遵循一个高度统一的处理模式,同时在细节上存在必要的差异。 **统一处理模式**: -所有`PayNotify`方法都遵循相同的高层逻辑:接收参数 -> 查找订单 -> 验证通道 -> 验证签名 -> 判断状态 -> 调用`SolvePaySuccess`或`SolvePayFail` -> 返回响应。这种模式确保了核心业务逻辑(订单状态更新)的集中化和一致性,避免了代码重复。 +所有`PayNotify`方法都遵循相同的高层逻辑:接收参数 -> 查找订单 -> 验证通道 -> 验证签名 -> 判断状态 -> 调用 +`SolvePaySuccess`或`SolvePayFail` -> 返回响应。这种模式确保了核心业务逻辑(订单状态更新)的集中化和一致性,避免了代码重复。 **渠道间差异**: 差异主要体现在以下几个方面: -1. **URL路径**:每个渠道有唯一的回调路径,如`/mfcard/notifyV2`和`/appleCard/notify`。 -2. **参数名称**:不同渠道使用的参数名不同。例如,爱博使用`attach`作为订单号,而天猫游戏使用`merchantOrder`。 -3. **签名算法**:虽然都使用签名验证,但具体的算法和密钥来源可能不同。`MFCardV2Impl`从`roadInfo.Params`中获取`appSecret`,而`TMAllGameImpl`使用一个名为`TmpEncrypt`的通用加密函数。 -4. **状态码定义**:各渠道的状态码含义不同。爱博用`"9"`表示成功,`"8"`表示失败;天猫游戏用`"finished"`表示成功。 + +1. **URL路径**:每个渠道有唯一的回调路径,如`/mfcard/notifyV2`和`/appleCard/notify`。 +2. **参数名称**:不同渠道使用的参数名不同。例如,爱博使用`attach`作为订单号,而天猫游戏使用`merchantOrder`。 +3. **签名算法**:虽然都使用签名验证,但具体的算法和密钥来源可能不同。`MFCardV2Impl`从`roadInfo.Params`中获取`appSecret`,而 + `TMAllGameImpl`使用一个名为`TmpEncrypt`的通用加密函数。 +4. **状态码定义**:各渠道的状态码含义不同。爱博用`"9"`表示成功,`"8"`表示失败;天猫游戏用`"finished"`表示成功。 这些差异通过在各自的`PayNotify`方法中实现特定的解析和验证逻辑来处理,而核心的订单解决逻辑则保持不变。 **Section sources** + - [mf178_v2.go](file://internal/service/supplier/third_party/mf178_v2.go#L187-L253) - [apple.go](file://internal/service/supplier/third_party/apple.go#L202-L240) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L167-L223) @@ -135,18 +159,22 @@ M --> N[结束] 系统不仅处理来自支付渠道的回调,还负责向商户系统发送支付结果通知,并为此设计了完善的错误处理和重试机制,以确保最终一致性。 -当`SolvePaySuccess`或`SolvePayFail`被调用后,它们会异步触发`CreateOrderNotifyInfo`函数。该函数将商户的回调信息(包括订单号、金额、状态等)插入`notify_info`数据库表,并将订单号发送到名为`config.MqOrderNotify`的消息队列中。 +当`SolvePaySuccess`或`SolvePayFail`被调用后,它们会异步触发`CreateOrderNotifyInfo`函数。该函数将商户的回调信息(包括订单号、金额、状态等)插入 +`notify_info`数据库表,并将订单号发送到名为`config.MqOrderNotify`的消息队列中。 -`internal/service/notify/order_notify.go`文件中的`CreateOrderNotifyConsumer`函数是一个消息队列消费者,它监听该队列。每当收到一个订单号,它就会启动`SendOrderNotify`流程,向商户配置的`notifyUrl`发起HTTP GET请求。 +`internal/service/notify/order_notify.go`文件中的`CreateOrderNotifyConsumer`函数是一个消息队列消费者,它监听该队列。每当收到一个订单号,它就会启动 +`SendOrderNotify`流程,向商户配置的`notifyUrl`发起HTTP GET请求。 为了应对网络波动或商户服务器暂时不可用的情况,系统实现了指数退避重试策略: -- 第1次重试:延迟1分钟 -- 第2次重试:延迟2分钟 -- 第3次重试:延迟5分钟 -- 第4次重试:延迟15分钟 -- 第5次及以后:延迟30分钟 -这个策略由`GetOrderNotifyMinute`函数定义。如果在`consts.LimitTimes`(通常为5次)尝试后仍未能收到商户返回的`"SUCCESS"`响应,该订单的回调状态将被标记为`"fail"`,并停止重试。 +- 第1次重试:延迟1分钟 +- 第2次重试:延迟2分钟 +- 第3次重试:延迟5分钟 +- 第4次重试:延迟15分钟 +- 第5次及以后:延迟30分钟 + +这个策略由`GetOrderNotifyMinute`函数定义。如果在`consts.LimitTimes`(通常为5次)尝试后仍未能收到商户返回的`"SUCCESS"` +响应,该订单的回调状态将被标记为`"fail"`,并停止重试。 ```mermaid sequenceDiagram @@ -169,13 +197,17 @@ end ``` **Diagram sources** + - [order_notify.go](file://internal/service/notify/order_notify.go#L0-L218) - [pay_solve.go](file://internal/service/pay_solve.go#L148-L195) **Section sources** + - [order_notify.go](file://internal/service/notify/order_notify.go#L0-L218) - [pay_solve.go](file://internal/service/pay_solve.go#L148-L195) ## 结论 -kami_gateway的回调API系统是一个设计精良、健壮可靠的支付结果处理机制。它通过统一的`PayNotify`接口模式和集中的`SolvePaySuccess`/`SolvePayFail`服务,有效地管理了多个第三方支付渠道的集成。系统在接收和处理支付渠道通知时,严格执行订单查找、通道验证和签名验证,确保了数据的安全性。同时,通过基于消息队列和指数退避的重试机制,系统能够可靠地将支付结果通知到商户端,即使在面对网络或服务故障时,也能保证最终一致性。这种分层、模块化的设计使得系统易于维护和扩展,为平台的稳定运行提供了坚实的基础。 \ No newline at end of file +kami_gateway的回调API系统是一个设计精良、健壮可靠的支付结果处理机制。它通过统一的`PayNotify`接口模式和集中的 +`SolvePaySuccess`/`SolvePayFail` +服务,有效地管理了多个第三方支付渠道的集成。系统在接收和处理支付渠道通知时,严格执行订单查找、通道验证和签名验证,确保了数据的安全性。同时,通过基于消息队列和指数退避的重试机制,系统能够可靠地将支付结果通知到商户端,即使在面对网络或服务故障时,也能保证最终一致性。这种分层、模块化的设计使得系统易于维护和扩展,为平台的稳定运行提供了坚实的基础。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/API参考/支付API.md b/.qoder/repowiki/zh/content/API参考/支付API.md index 9ad9aaa..fa26af5 100644 --- a/.qoder/repowiki/zh/content/API参考/支付API.md +++ b/.qoder/repowiki/zh/content/API参考/支付API.md @@ -13,6 +13,7 @@ ## 目录 + 1. [简介](#简介) 2. [核心功能概述](#核心功能概述) 3. [API端点详解](#api端点详解) @@ -25,25 +26,33 @@ 10. [JSON请求/响应示例](#json请求响应示例) ## 简介 -本文档详细说明了kami_gateway系统中与支付相关的两个核心API端点:`/gateway/scan` 和 `/gateway/createOrder`。这两个接口负责处理商户发起的支付下单请求,涵盖从参数验证、签名校验、订单生成到最终调用第三方支付渠道的完整流程。文档重点解析了请求参数结构、MD5签名机制、支付通道选择逻辑(ChooseRoadV2)、订单记录生成以及自有渠道与第三方渠道的区别处理方式。 + +本文档详细说明了kami_gateway系统中与支付相关的两个核心API端点:`/gateway/scan` 和 `/gateway/createOrder` +。这两个接口负责处理商户发起的支付下单请求,涵盖从参数验证、签名校验、订单生成到最终调用第三方支付渠道的完整流程。文档重点解析了请求参数结构、MD5签名机制、支付通道选择逻辑(ChooseRoadV2)、订单记录生成以及自有渠道与第三方渠道的区别处理方式。 **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) ## 核心功能概述 -/gateway/scan 和 /gateway/createOrder 是kami_gateway处理支付请求的核心入口。它们共同实现了商户支付订单的创建与处理,支持扫码支付场景。系统通过统一的参数验证、商户身份识别、支付通道选择和订单状态管理,确保交易的安全性与可靠性。两个接口均采用基于MD5的签名验证机制来保证请求的完整性,并通过灵活的支付通道配置支持多种第三方支付供应商。 + +/gateway/scan 和 /gateway/createOrder +是kami_gateway处理支付请求的核心入口。它们共同实现了商户支付订单的创建与处理,支持扫码支付场景。系统通过统一的参数验证、商户身份识别、支付通道选择和订单状态管理,确保交易的安全性与可靠性。两个接口均采用基于MD5的签名验证机制来保证请求的完整性,并通过灵活的支付通道配置支持多种第三方支付供应商。 **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) - [pay_service.go](file://internal/service/pay_service.go#L30-L74) ## API端点详解 ### /gateway/scan 端点 + 该端点用于处理商户直接提交的扫码支付请求。它接收包含订单信息的HTTP GET请求,执行完整的支付流程,包括参数验证、签名校验、支付通道选择、订单生成及调用上游支付接口。 **请求方法**: GET **主要参数**: + - `orderNo`: 商户订单号 - `productCode`: 产品编码 - `orderPrice`: 订单金额 @@ -55,11 +64,13 @@ - `deviceId`: 设备ID ### /gateway/createOrder 端点 + 该端点用于创建支付订单并返回支付链接(payUrl)。与/gateway/scan不同,此接口不立即执行支付动作,而是生成一个可后续访问的支付页面链接,适用于需要跳转支付页面的场景。 **请求方法**: POST **请求体格式**: JSON **主要参数**: + - `payKey`: 商户密钥 - `orderNo`: 商户订单号 - `orderPrice`: 订单金额 @@ -70,10 +81,12 @@ - `sign`: 签名值 **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) - [order.go](file://internal/schema/request/order.go#L1-L35) ## 请求流程分析 + 当商户调用支付API时,系统执行以下关键步骤: 1. **参数提取与基础验证**:从请求中提取所有参数并进行非空和格式校验。 @@ -99,31 +112,37 @@ I --> J[返回响应] ``` **Diagram sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) - [pay_service.go](file://internal/service/pay_service.go#L30-L74) **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) - [pay_service.go](file://internal/service/pay_service.go#L30-L74) ## 签名验证机制 + 系统采用基于MD5的签名验证机制来保障API请求的安全性。相关逻辑实现在`sign_verify.go`文件中,主要涉及以下函数: - `GetMD5SignMF`: 生成MD5签名的核心函数,对参数按字典序排序后拼接并附加商户密钥进行MD5计算。 - `Md5MFVerify`: 验证请求签名的函数,会排除`sign`、`deviceId`和`ip`字段后重新计算签名进行比对。 签名生成规则如下: + 1. 将除`sign`、`deviceId`、`ip`外的所有请求参数按键名进行字典序排序。 2. 拼接所有参数为`key1value1key2value2...`格式。 3. 在末尾追加商户密钥(`paySecret`)。 4. 对最终字符串进行MD5哈希计算,并转换为小写。 **Section sources** + - [sign_verify.go](file://internal/utils/sign_verify.go#L1-L104) ## 响应结构说明 ### ScanSuccessData 成功响应 + 当支付请求成功处理时,返回`ScanSuccessData`结构: ```json @@ -138,17 +157,18 @@ I --> J[返回响应] } ``` -| 字段 | 类型 | 描述 | -|------|------|------| -| orderNo | string | 系统生成的订单号 | -| sign | string | 响应签名 | -| orderPrice | string | 订单金额 | +| 字段 | 类型 | 描述 | +|------------|--------|----------------| +| orderNo | string | 系统生成的订单号 | +| sign | string | 响应签名 | +| orderPrice | string | 订单金额 | | statusCode | string | 状态码 ("00"表示成功) | -| msg | string | 响应消息 | -| code | int | 业务状态码 (0表示成功) | -| payUrl | string | 支付链接(如有) | +| msg | string | 响应消息 | +| code | int | 业务状态码 (0表示成功) | +| payUrl | string | 支付链接(如有) | ### ScanFailData 失败响应 + 当支付请求处理失败时,返回`ScanFailData`结构: ```json @@ -160,20 +180,23 @@ I --> J[返回响应] } ``` -| 字段 | 类型 | 描述 | -|------|------|------| -| payKey | string | 商户密钥 | +| 字段 | 类型 | 描述 | +|------------|--------|----------------| +| payKey | string | 商户密钥 | | statusCode | string | 状态码 ("01"表示失败) | -| msg | string | 错误消息 | -| code | int | 业务状态码 (-1表示失败) | +| msg | string | 错误消息 | +| code | int | 业务状态码 (-1表示失败) | **Section sources** + - [pay_resp.go](file://internal/schema/response/pay_resp.go#L1-L38) ## 错误处理与限制策略 + 系统实现了多层次的错误处理与安全限制机制: ### 订单重复提交限制 + 通过`sync.Map`类型的`orderSubmitLimiter`全局变量实现订单号提交频率限制。默认情况下,同一订单号在2秒内只能提交一次,防止恶意重放攻击。 ```go @@ -181,20 +204,25 @@ func isAllowed(orderNo string, intervalSec int64) bool ``` ### IP限制机制 + 系统支持基于IP的访问控制,可通过`backend.GetIPIsRestricted`函数检查特定IP是否被限制。虽然相关代码被注释,但架构上已预留此功能接口。 ### 其他验证规则 + - **商户状态验证**:确保商户处于激活状态(`ACTIVE`) - **通道配置验证**:检查商户是否已配置对应支付通道 - **金额范围验证**:确保订单金额在通道允许的最小/最大限额内 - **产品编码验证**:确认产品编码对应的支付通道已配置 **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) - [order_info.go](file://internal/models/order/order_info.go#L1-L437) ## 支付通道选择逻辑 -`ChooseRoadV2`函数是支付通道选择的核心逻辑,其实现位于`pay_service.go`文件中。该函数根据商户请求中的`productCode`查找对应的支付通道配置,并进行一系列有效性验证: + +`ChooseRoadV2`函数是支付通道选择的核心逻辑,其实现位于`pay_service.go`文件中。该函数根据商户请求中的`productCode` +查找对应的支付通道配置,并进行一系列有效性验证: 1. 解析订单金额 2. 根据`productCode`获取`roadInfo` @@ -206,10 +234,12 @@ func isAllowed(orderNo string, intervalSec int64) bool 该函数确保只有符合所有业务规则的请求才能进入后续支付流程。 **Section sources** + - [pay_service.go](file://internal/service/pay_service.go#L30-L74) - [road_info.go](file://internal/models/road/road_info.go#L1-L202) ## 第三方支付渠道调用 + 系统通过工厂模式管理第三方支付渠道,核心函数为`GetPaySupplierByCode`,定义在`third_party/init.go`中: ```go @@ -228,12 +258,14 @@ func GetPaySupplierByCode(code string) supplier.PayInterface { 系统支持区分自有渠道和第三方渠道:自有渠道可能直接返回支付链接,而第三方渠道需通过API调用完成支付。 **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) - [init.go](file://internal/service/supplier/third_party/init.go#L151-L153) ## JSON请求/响应示例 ### /gateway/createOrder 请求示例 + ```json { "payKey": "merchant_123", @@ -248,6 +280,7 @@ func GetPaySupplierByCode(code string) supplier.PayInterface { ``` ### /gateway/createOrder 成功响应示例 + ```json { "code": 0, @@ -265,6 +298,7 @@ func GetPaySupplierByCode(code string) supplier.PayInterface { ``` ### /gateway/scan 失败响应示例 + ```json { "payKey": "merchant_123", @@ -275,6 +309,7 @@ func GetPaySupplierByCode(code string) supplier.PayInterface { ``` **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L543) - [order.go](file://internal/schema/request/order.go#L1-L35) - [pay_resp.go](file://internal/schema/response/pay_resp.go#L1-L38) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/API参考/查询API.md b/.qoder/repowiki/zh/content/API参考/查询API.md index b6753a1..16d2cd6 100644 --- a/.qoder/repowiki/zh/content/API参考/查询API.md +++ b/.qoder/repowiki/zh/content/API参考/查询API.md @@ -9,6 +9,7 @@ ## 目录 + 1. [简介](#简介) 2. [商户查询接口](#商户查询接口) 3. [供应商订单查询接口](#供应商订单查询接口) @@ -16,15 +17,18 @@ 5. [响应格式](#响应格式) ## 简介 + 本文档详细说明了kami_gateway系统中的查询API,包括商户查询、供应商订单查询和订单重新调度功能。文档涵盖了接口的认证机制、参数验证流程、业务逻辑处理以及各种情况下的响应格式。 ## 商户查询接口 `/gateway/merchant/query`端点为下游商户提供订单查询服务。该接口通过appKey、timestamp和sign参数进行安全验证,确保只有授权商户可以查询其订单信息。 -接口首先验证所有必需参数是否提供,然后通过appKey查找商户信息。认证机制使用两种签名验证方法:`GetMD5SignMF`和`GetMD5Sign`,确保签名的正确性。验证通过后,系统查询订单信息并返回包含订单号、卡号、卡密、面值等敏感信息的响应。 +接口首先验证所有必需参数是否提供,然后通过appKey查找商户信息。认证机制使用两种签名验证方法:`GetMD5SignMF`和`GetMD5Sign` +,确保签名的正确性。验证通过后,系统查询订单信息并返回包含订单号、卡号、卡密、面值等敏感信息的响应。 **Section sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L140-L224) - [sign_verify.go](file://internal/utils/sign_verify.go#L89-L102) @@ -32,7 +36,8 @@ `/gateway/supplier/order/query`端点为上游供应商提供订单查询服务。该接口允许供应商通过bankOrderId查询订单状态和相关信息。 -接口处理流程包括:接收bankOrderId参数,记录查询日志,然后调用`SupplierOrderQueryResult`函数获取查询结果。该函数会从数据库中检索订单信息,并以字符串形式返回结果。 +接口处理流程包括:接收bankOrderId参数,记录查询日志,然后调用`SupplierOrderQueryResult` +函数获取查询结果。该函数会从数据库中检索订单信息,并以字符串形式返回结果。 ```mermaid sequenceDiagram @@ -47,9 +52,11 @@ participant 查询服务 as query.SupplierOrderQueryResult ``` **Diagram sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L30-L40) **Section sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L30-L40) - [merchant_query.go](file://internal/schema/query/merchant_query.go#L28-L75) @@ -62,6 +69,7 @@ participant 查询服务 as query.SupplierOrderQueryResult 3. 通道必须允许重新调度 调度执行流程: + 1. 验证调度条件 2. 修改订单状态为"wait" 3. 调用供应商的Scan方法重新提交订单 @@ -84,14 +92,17 @@ Start([开始]) --> 验证订单状态 ``` **Diagram sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L42-L95) **Section sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L42-L95) ## 响应格式 ### 成功响应示例 + ```json { "code": 0, @@ -109,6 +120,7 @@ Start([开始]) --> 验证订单状态 ``` ### 错误响应示例 + ```json { "code": -1, @@ -164,7 +176,9 @@ Resp[OrderQueryResp] --> OrderQueryResp : "包含" ``` **Diagram sources** + - [response.go](file://internal/models/response/response.go#L1-L28) **Section sources** + - [response.go](file://internal/models/response/response.go#L1-L28) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/开发者指南.md b/.qoder/repowiki/zh/content/开发者指南.md index 36a85f7..9829bd5 100644 --- a/.qoder/repowiki/zh/content/开发者指南.md +++ b/.qoder/repowiki/zh/content/开发者指南.md @@ -13,6 +13,7 @@ ## 目录 + 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [开发环境设置](#开发环境设置) @@ -23,9 +24,11 @@ 8. [测试与覆盖率](#测试与覆盖率) ## 简介 + 本指南旨在为新加入的开发者提供一个全面的入门指导,帮助您快速搭建本地开发环境并理解项目的基本架构。我们将详细介绍从克隆仓库到成功运行应用的完整流程,包括环境配置、构建运行、Docker部署、调试技巧以及代码修改示例。 ## 项目结构 + 本项目采用模块化设计,主要目录结构如下: - `conf/`:配置文件目录,包含应用的主要配置文件 `app.conf` @@ -53,15 +56,19 @@ J --> L[third_party] ``` **图示来源** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) **本节来源** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) ## 开发环境设置 + ### Go版本要求 + 根据 `go.mod` 文件中的声明,本项目需要 Go 1.24.0 或更高版本: ```go @@ -73,6 +80,7 @@ toolchain go1.24.6 建议使用 Go 1.24.6 工具链以确保兼容性。 ### 依赖安装 + 使用 Go Modules 管理依赖,通过以下命令安装所有依赖: ```bash @@ -80,6 +88,7 @@ go mod tidy ``` 此命令将根据 `go.mod` 文件下载并整理所有必需的依赖包,包括: + - Beego Web框架 - OpenTelemetry追踪库 - Redis客户端 @@ -87,6 +96,7 @@ go mod tidy - 各种工具库 ### 数据库初始化 + 根据 `conf/app.conf` 文件中的配置,数据库连接信息如下: ```ini @@ -100,16 +110,20 @@ debug = true ``` 初始化步骤: + 1. 确保MySQL服务正在运行 2. 创建名为 `kami` 的数据库 3. 导入项目所需的表结构和初始数据(具体SQL文件未在项目中提供) **本节来源** + - [go.mod](file://go.mod#L2-L85) - [conf/app.conf](file://conf/app.conf#L20-L25) ## 构建与运行 + ### 构建方法 + 项目提供了 `build.sh` 脚本用于构建可执行文件: ```bash @@ -117,14 +131,17 @@ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go ``` 此脚本配置了以下构建参数: + - `CGO_ENABLED=0`:禁用CGO,使二进制文件静态链接 - `GOOS=linux`:目标操作系统为Linux - `GOARCH=amd64`:目标架构为AMD64 ### 运行方法 + 有两种方式可以运行应用: #### 使用构建脚本 + ```bash # 构建 ./build.sh @@ -133,11 +150,13 @@ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go ``` #### 直接运行 + ```bash go run main.go ``` ### 应用初始化流程 + `main.go` 文件中的 `main()` 函数定义了应用的初始化流程: ```mermaid @@ -160,16 +179,20 @@ Web --> End([应用运行中]) ``` **图示来源** + - [main.go](file://main.go#L23-L57) **本节来源** + - [main.go](file://main.go#L1-L58) - [build.sh](file://build.sh#L1-L2) ## Docker Compose 配置 + 项目提供了两个Docker Compose配置文件,分别用于本地开发和生产部署。 ### 本地开发配置 + `deploy/docker-compose-local.yaml` 文件定义了本地开发环境: ```yaml @@ -187,11 +210,13 @@ services: ``` 特点: + - 使用 `latest` 标签的镜像 - 将容器的12309端口映射到主机的12309端口 - 连接到外部网络 `1panel-network` ### 生产部署配置 + `deploy/docker-compose.yaml` 文件定义了生产环境: ```yaml @@ -215,17 +240,21 @@ services: ``` 特点: + - 使用 `$VERSION` 环境变量指定镜像版本 - 设置容器自动重启 - 仅允许本地回环地址访问服务端口 - 挂载外部配置和日志目录 **本节来源** + - [deploy/docker-compose.yaml](file://deploy/docker-compose.yaml#L1-L23) - [deploy/docker-compose-local.yaml](file://deploy/docker-compose-local.yaml#L1-L17) ## 调试与性能分析 + ### pprof性能分析 + 项目已通过导入 `_ "net/http/pprof"` 包启用了pprof性能分析功能。可以通过以下URL访问pprof接口: - `http://localhost:12309/debug/pprof/`:pprof主页 @@ -233,6 +262,7 @@ services: - `http://localhost:12309/debug/pprof/heap`:内存堆分析 使用方法: + ```bash # 获取30秒的CPU性能分析数据 go tool pprof http://localhost:12309/debug/pprof/profile?seconds=30 @@ -242,6 +272,7 @@ go tool pprof http://localhost:12309/debug/pprof/heap ``` ### 日志配置 + 根据 `conf/app.conf` 文件,日志配置如下: ```ini @@ -255,11 +286,14 @@ maxdays=10 日志级别为7(DEBUG级别),日志文件保存在 `./logs/jhmerchant.log`,最多保留10天。 **本节来源** + - [main.go](file://main.go#L10-L11) - [conf/app.conf](file://conf/app.conf#L7-L15) ## 代码修改示例 + ### 添加健康检查API + 以下是如何添加一个新的健康检查API的示例: 1. **创建控制器方法**:在 `internal/controllers/base_controller.go` 中添加健康检查方法 @@ -286,11 +320,14 @@ web.Router("/health", &controllers.BaseController{}, "*:HealthCheck") 此示例展示了项目的基本代码结构:控制器处理请求,路由配置定义端点。通过这种方式,您可以轻松添加新的API端点。 **本节来源** + - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) - [main.go](file://main.go#L1-L58) ## 测试与覆盖率 + ### 运行测试套件 + 使用Go内置的测试工具运行所有测试: ```bash @@ -300,6 +337,7 @@ go test ./... 此命令将递归执行项目中所有包的测试文件(以 `_test.go` 结尾的文件)。 ### 查看覆盖率报告 + 生成测试覆盖率报告: ```bash @@ -316,7 +354,9 @@ go tool cover -html=coverage.out -o coverage.html HTML报告将显示每行代码的执行情况,绿色表示已覆盖,红色表示未覆盖。 ### 测试文件示例 + 项目中包含多个测试文件,如: + - `internal/dto/order_test.go`:DTO层测试 - `internal/service/supplier/third_party/pool/worker_test.go`:第三方供应商服务测试 - `internal/cache/redis_test.go`:Redis缓存测试 @@ -324,6 +364,7 @@ HTML报告将显示每行代码的执行情况,绿色表示已覆盖,红色 这些测试文件遵循Go测试惯例,使用 `testing` 包和 `testify` 断言库。 **本节来源** + - [internal/dto/order_test.go](file://internal/dto/order_test.go#L1-L65) - [internal/cache/redis_test.go](file://internal/cache/redis_test.go#L1-L2) - [go.mod](file://go.mod#L70-L71) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/Beego 框架集成.md b/.qoder/repowiki/zh/content/技术栈与依赖/Beego 框架集成.md index d060fb6..01e829f 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/Beego 框架集成.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/Beego 框架集成.md @@ -11,6 +11,7 @@ ## 目录 + 1. [介绍](#介绍) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) @@ -22,7 +23,9 @@ 9. [结论](#结论) ## 介绍 -本文档详细说明了 Beego v2 框架在 kami_gateway 项目中的集成与应用。重点阐述了 Web 服务的启动流程、路由注册机制、控制器继承结构、中间件集成方式、RESTful API 接口的注解路由映射、Beego ORM 的自动模型注册机制及其与 MySQL 数据库的交互模式。同时提供性能调优建议、常见陷阱规避策略以及框架升级兼容性注意事项。 + +本文档详细说明了 Beego v2 框架在 kami_gateway 项目中的集成与应用。重点阐述了 Web 服务的启动流程、路由注册机制、控制器继承结构、中间件集成方式、RESTful +API 接口的注解路由映射、Beego ORM 的自动模型注册机制及其与 MySQL 数据库的交互模式。同时提供性能调优建议、常见陷阱规避策略以及框架升级兼容性注意事项。 ## 项目结构 @@ -56,18 +59,22 @@ M --> Z[init.go] ``` **图表来源** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) **章节来源** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) ## 核心组件 -kami_gateway 项目基于 Beego v2 框架构建,实现了网关服务的核心功能,包括订单处理、支付回调、商户查询等。系统通过 Beego 的 MVC 架构组织代码,利用其强大的路由、控制器、ORM 和中间件功能,构建了一个高并发、可扩展的支付网关系统。 +kami_gateway 项目基于 Beego v2 框架构建,实现了网关服务的核心功能,包括订单处理、支付回调、商户查询等。系统通过 Beego 的 MVC +架构组织代码,利用其强大的路由、控制器、ORM 和中间件功能,构建了一个高并发、可扩展的支付网关系统。 **章节来源** + - [main.go](file://main.go#L1-L58) - [internal/controllers/base_controller.go](file://internal/controllers/base_controller.go#L1-L9) - [internal/models/init.go](file://internal/models/init.go#L1-L56) @@ -92,6 +99,7 @@ Middleware --> Logging[日志记录] ``` **图表来源** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) - [internal/controllers/base_controller.go](file://internal/controllers/base_controller.go#L1-L9) @@ -100,7 +108,8 @@ Middleware --> Logging[日志记录] ### Web 服务启动流程 -Web 服务的启动通过 `web.Run()` 方法实现。在 `main.go` 文件中,程序首先进行各种初始化操作,包括配置加载、代理池初始化、分布式追踪初始化、消息队列消费者启动、缓存服务启动等,最后调用 `web.Run()` 启动 Web 服务器。 +Web 服务的启动通过 `web.Run()` 方法实现。在 `main.go` 文件中,程序首先进行各种初始化操作,包括配置加载、代理池初始化、分布式追踪初始化、消息队列消费者启动、缓存服务启动等,最后调用 +`web.Run()` 启动 Web 服务器。 ```mermaid sequenceDiagram @@ -122,14 +131,17 @@ Web-->>Main : 服务启动成功 ``` **图表来源** + - [main.go](file://main.go#L1-L58) **章节来源** + - [main.go](file://main.go#L1-L58) ### 路由注册机制 -路由注册在 `internal/routers/router.go` 文件的 `init()` 函数中完成。系统使用 `web.Router()` 方法将不同的 URL 路径映射到相应的控制器和方法。同时,通过 `web.InsertFilterChain()` 注册了全局中间件,用于处理分布式追踪。 +路由注册在 `internal/routers/router.go` 文件的 `init()` 函数中完成。系统使用 `web.Router()` 方法将不同的 URL +路径映射到相应的控制器和方法。同时,通过 `web.InsertFilterChain()` 注册了全局中间件,用于处理分布式追踪。 ```mermaid flowchart TD @@ -155,14 +167,17 @@ O --> T["/walMart/notify -> WalMartImpl.PayNotify"] ``` **图表来源** + - [internal/routers/router.go](file://internal/routers/router.go#L12-L74) **章节来源** + - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) ### 控制器继承结构 -控制器采用继承结构,所有控制器都继承自 `BaseGateway` 结构体,而 `BaseGateway` 又继承自 Beego 的 `web.Controller`。这种设计实现了代码复用和统一的基类功能。 +控制器采用继承结构,所有控制器都继承自 `BaseGateway` 结构体,而 `BaseGateway` 又继承自 Beego 的 `web.Controller` +。这种设计实现了代码复用和统一的基类功能。 ```mermaid classDiagram @@ -205,18 +220,21 @@ BaseGateway <|-- PayForGateway ``` **图表来源** + - [internal/controllers/base_controller.go](file://internal/controllers/base_controller.go#L6-L8) - [internal/controllers/scan_controller.go](file://internal/controllers/scan_controller.go#L64-L66) - [internal/controllers/order_controller.go](file://internal/controllers/order_controller.go#L26-L28) **章节来源** + - [internal/controllers/base_controller.go](file://internal/controllers/base_controller.go#L1-L9) - [internal/controllers/scan_controller.go](file://internal/controllers/scan_controller.go#L1-L542) - [internal/controllers/order_controller.go](file://internal/controllers/order_controller.go#L1-L225) ### 中间件集成方式 -系统通过 `web.InsertFilterChain()` 方法集成全局中间件。在 `router.go` 文件中,所有请求路径 (`*`) 都会经过 `otelTrace.Middleware` 中间件处理,实现分布式追踪功能。 +系统通过 `web.InsertFilterChain()` 方法集成全局中间件。在 `router.go` 文件中,所有请求路径 (`*`) 都会经过 +`otelTrace.Middleware` 中间件处理,实现分布式追踪功能。 ```mermaid sequenceDiagram @@ -233,9 +251,11 @@ Beego->>Client : HTTP响应 ``` **图表来源** + - [internal/routers/router.go](file://internal/routers/router.go#L12-L14) **章节来源** + - [internal/routers/router.go](file://internal/routers/router.go#L12-L74) ### RESTful API 接口映射 @@ -267,15 +287,18 @@ end ``` **图表来源** + - [internal/routers/router.go](file://internal/routers/router.go#L18-L21) - [internal/controllers/scan_controller.go](file://internal/controllers/scan_controller.go#L69-L541) **章节来源** + - [internal/controllers/scan_controller.go](file://internal/controllers/scan_controller.go#L69-L541) ### Beego ORM 自动模型注册 -Beego ORM 的自动模型注册在 `internal/models/init.go` 文件的 `init()` 函数中完成。系统通过 `orm.RegisterModel()` 方法注册所有数据模型,实现数据库表的自动映射和管理。 +Beego ORM 的自动模型注册在 `internal/models/init.go` 文件的 `init()` 函数中完成。系统通过 `orm.RegisterModel()` +方法注册所有数据模型,实现数据库表的自动映射和管理。 ```mermaid classDiagram @@ -342,12 +365,14 @@ models --> OrderInfo : 注册模型 ``` **图表来源** + - [internal/models/init.go](file://internal/models/init.go#L1-L56) - [internal/models/accounts/account.go](file://internal/models/accounts/account.go#L1-L114) - [internal/models/merchant/merchant_info.go](file://internal/models/merchant/merchant_info.go#L1-L208) - [internal/models/order/order_info.go](file://internal/models/order/order_info.go#L1-L436) **章节来源** + - [internal/models/init.go](file://internal/models/init.go#L1-L56) ## 依赖分析 @@ -377,10 +402,12 @@ otelTrace --> OTel ``` **图表来源** + - [main.go](file://main.go#L1-L58) - [go.mod](file://go.mod) **章节来源** + - [main.go](file://main.go#L1-L58) ## 性能考虑 @@ -392,6 +419,7 @@ otelTrace --> OTel 5. **异步处理**:将耗时操作(如回调通知、消息发送)放入协程池异步执行,避免阻塞主流程。 **章节来源** + - [internal/service/pay_solve.go](file://internal/service/pay_solve.go#L1-L580) - [internal/controllers/scan_controller.go](file://internal/controllers/scan_controller.go#L1-L542) @@ -400,14 +428,17 @@ otelTrace --> OTel 1. **服务无法启动**:检查 `main.go` 中的初始化顺序,确保数据库连接、缓存服务等依赖项正常启动。 2. **路由不生效**:确认 `routers/router.go` 文件被正确导入(`_ "gateway/internal/routers"`),且路由路径和控制器方法名正确。 3. **数据库连接失败**:检查 `models/init.go` 中的数据库配置是否正确,确保 MySQL 服务正常运行。 -4. **ORM 模型未注册**:确认 `models/init.go` 文件被正确导入(`_ "gateway/internal/models"`),且所有模型都已通过 `RegisterModel` 注册。 +4. **ORM 模型未注册**:确认 `models/init.go` 文件被正确导入(`_ "gateway/internal/models"`),且所有模型都已通过 + `RegisterModel` 注册。 5. **中间件不生效**:检查 `InsertFilterChain` 的调用时机,确保在路由注册之前完成中间件注册。 **章节来源** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) - [internal/models/init.go](file://internal/models/init.go#L1-L56) ## 结论 -kami_gateway 项目成功集成了 Beego v2 框架,构建了一个功能完整、性能优良的支付网关系统。通过合理的架构设计和代码组织,系统实现了高内聚、低耦合的模块化结构。Beego 框架的路由、控制器、ORM 和中间件功能为系统开发提供了强大支持,使得开发效率和代码质量得到显著提升。未来可进一步优化异步处理机制,增强系统的可扩展性和容错能力。 \ No newline at end of file +kami_gateway 项目成功集成了 Beego v2 框架,构建了一个功能完整、性能优良的支付网关系统。通过合理的架构设计和代码组织,系统实现了高内聚、低耦合的模块化结构。Beego +框架的路由、控制器、ORM 和中间件功能为系统开发提供了强大支持,使得开发效率和代码质量得到显著提升。未来可进一步优化异步处理机制,增强系统的可扩展性和容错能力。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/HTTP中间件集成.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/HTTP中间件集成.md index 2e8f097..a8e1392 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/HTTP中间件集成.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/HTTP中间件集成.md @@ -11,6 +11,7 @@ ## 目录 + 1. [简介](#简介) 2. [核心组件](#核心组件) 3. [熔断器保护机制](#熔断器保护机制) @@ -21,7 +22,10 @@ 8. [结论](#结论) ## 简介 -本文档详细说明了 OpenTelemetry 中间件在 Beego 框架中的实现机制,重点分析了全链路追踪功能的实现方式。文档涵盖了中间件如何作为 Beego 的 FilterFunc 注入请求处理链,如何从 HeaderCarrier 提取上游 trace context 并创建新的 Server Span,以及熔断器保护机制如何确保在追踪系统异常时不影响核心业务流程。同时,文档还分析了中间件的性能影响和优化策略。 + +本文档详细说明了 OpenTelemetry 中间件在 Beego 框架中的实现机制,重点分析了全链路追踪功能的实现方式。文档涵盖了中间件如何作为 +Beego 的 FilterFunc 注入请求处理链,如何从 HeaderCarrier 提取上游 trace context 并创建新的 Server +Span,以及熔断器保护机制如何确保在追踪系统异常时不影响核心业务流程。同时,文档还分析了中间件的性能影响和优化策略。 ## 核心组件 @@ -55,11 +59,13 @@ CircuitBreaker --> CircuitBreakerState : "包含" ``` **Diagram sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L21-L140) - [circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L5-L11) - [consts.go](file://internal/otelTrace/consts.go#L50-L55) **Section sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L1-L141) - [circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L1-L51) - [consts.go](file://internal/otelTrace/consts.go#L1-L56) @@ -91,16 +97,19 @@ end note ``` **Diagram sources** + - [circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L5-L50) - [consts.go](file://internal/otelTrace/consts.go#L50-L55) **Section sources** + - [circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L1-L51) - [consts.go](file://internal/otelTrace/consts.go#L50-L55) ## 中间件执行流程 -OpenTelemetry 中间件作为 Beego 框架的 FilterFunc 被注入到请求处理链中,实现了全链路追踪功能。中间件在请求开始时从 HeaderCarrier 提取上游 trace context,并创建新的 Server Span。 +OpenTelemetry 中间件作为 Beego 框架的 FilterFunc 被注入到请求处理链中,实现了全链路追踪功能。中间件在请求开始时从 +HeaderCarrier 提取上游 trace context,并创建新的 Server Span。 ```mermaid sequenceDiagram @@ -142,10 +151,12 @@ Middleware->>Client : 返回响应 ``` **Diagram sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L21-L140) - [utils.go](file://internal/otelTrace/utils.go#L60-L75) **Section sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L21-L140) - [utils.go](file://internal/otelTrace/utils.go#L60-L75) @@ -181,10 +192,12 @@ EndSpan --> End([请求结束]) ``` **Diagram sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L21-L140) - [utils.go](file://internal/otelTrace/utils.go#L80-L90) **Section sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L21-L140) - [utils.go](file://internal/otelTrace/utils.go#L80-L90) @@ -221,10 +234,12 @@ StartMonitor --> monitorExporterHealth["monitorExporterHealth()"] ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [consts.go](file://internal/otelTrace/consts.go#L10-L45) **Section sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [consts.go](file://internal/otelTrace/consts.go#L10-L45) @@ -252,6 +267,7 @@ style simple.go fill:#9ff,stroke:#333 ``` **Diagram sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L1-L141) - [circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L1-L51) - [consts.go](file://internal/otelTrace/consts.go#L1-L56) @@ -260,6 +276,7 @@ style simple.go fill:#9ff,stroke:#333 - [simple.go](file://internal/otelTrace/simple.go#L1-L93) **Section sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L1-L141) - [circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L1-L51) - [consts.go](file://internal/otelTrace/consts.go#L1-L56) @@ -269,8 +286,12 @@ style simple.go fill:#9ff,stroke:#333 ## 结论 -OpenTelemetry 中间件在 Beego 框架中的实现充分考虑了生产环境的需求,通过熔断器保护机制确保了系统的稳定性。中间件能够有效地集成到 Beego 的请求处理链中,实现全链路追踪功能。通过从 HeaderCarrier 提取上游 trace context 并创建新的 Server Span,实现了跨服务的追踪链路。中间件添加了丰富的监控指标,包括 HTTP 方法、URL、状态码、响应大小、持续时间以及客户端 IP 等,为系统监控和问题排查提供了有力支持。 +OpenTelemetry 中间件在 Beego 框架中的实现充分考虑了生产环境的需求,通过熔断器保护机制确保了系统的稳定性。中间件能够有效地集成到 +Beego 的请求处理链中,实现全链路追踪功能。通过从 HeaderCarrier 提取上游 trace context 并创建新的 Server +Span,实现了跨服务的追踪链路。中间件添加了丰富的监控指标,包括 HTTP 方法、URL、状态码、响应大小、持续时间以及客户端 IP +等,为系统监控和问题排查提供了有力支持。 -熔断器机制在追踪系统异常时能够捕获错误并降级,确保不影响核心业务流程。defer 函数中实现了 panic 的记录和优雅降级返回 500 错误,同时确保 Span 能够正确结束。系统初始化过程配置了生产环境优化的参数,包括网络超时、重试机制、批量处理等,有效降低了中间件对系统性能的影响。 +熔断器机制在追踪系统异常时能够捕获错误并降级,确保不影响核心业务流程。defer 函数中实现了 panic 的记录和优雅降级返回 500 +错误,同时确保 Span 能够正确结束。系统初始化过程配置了生产环境优化的参数,包括网络超时、重试机制、批量处理等,有效降低了中间件对系统性能的影响。 总体而言,该中间件设计合理,功能完善,能够在保证系统稳定性的同时提供全面的监控能力,是生产环境中理想的分布式追踪解决方案。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/OpenTelemetry 分布式追踪.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/OpenTelemetry 分布式追踪.md index 47d22c2..5ba7579 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/OpenTelemetry 分布式追踪.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/OpenTelemetry 分布式追踪.md @@ -12,6 +12,7 @@ ## 目录 + 1. [OpenTelemetry 初始化机制](#opentelemetry-初始化机制) 2. [全局上下文与Span生命周期管理](#全局上下文与span生命周期管理) 3. [日志与追踪上下文关联](#日志与追踪上下文关联) @@ -22,9 +23,12 @@ ## OpenTelemetry 初始化机制 -`otelTrace.InitTracer()` 函数是 OpenTelemetry 在 kami_gateway 中的核心初始化入口,负责配置和启动追踪、指标和日志的导出功能。该函数在 `main.go` 的 `main()` 函数中被调用,是整个分布式追踪系统的起点。 +`otelTrace.InitTracer()` 函数是 OpenTelemetry 在 kami_gateway 中的核心初始化入口,负责配置和启动追踪、指标和日志的导出功能。该函数在 +`main.go` 的 `main()` 函数中被调用,是整个分布式追踪系统的起点。 -初始化过程首先创建 OTLP (OpenTelemetry Protocol) 的 gRPC 客户端,用于将追踪数据发送到指定的收集器(collector)。在 `internal/otelTrace/init.go` 文件中,通过 `otlptracegrpc.NewClient` 配置了生产环境优化的网络参数,包括 5 秒的超时时间、启用重试机制(初始间隔 1 秒,最大间隔 10 秒)以及使用 gzip 压缩来减少网络传输量。 +初始化过程首先创建 OTLP (OpenTelemetry Protocol) 的 gRPC 客户端,用于将追踪数据发送到指定的收集器(collector)。在 +`internal/otelTrace/init.go` 文件中,通过 `otlptracegrpc.NewClient` 配置了生产环境优化的网络参数,包括 5 +秒的超时时间、启用重试机制(初始间隔 1 秒,最大间隔 10 秒)以及使用 gzip 压缩来减少网络传输量。 ```mermaid sequenceDiagram @@ -44,20 +48,26 @@ InitTracer-->>main : 返回清理函数 ``` **Diagram sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L29-L205) - [main.go](file://main.go#L1-L58) **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L29-L205) - [main.go](file://main.go#L1-L58) ## 全局上下文与Span生命周期管理 -kami_gateway 使用 `InitCtx` 作为全局的上下文(Context),它在 `internal/otelTrace/consts.go` 文件中被定义为 `context.Background()`。这个上下文贯穿整个应用的生命周期,用于传递追踪信息和控制取消信号。 +kami_gateway 使用 `InitCtx` 作为全局的上下文(Context),它在 `internal/otelTrace/consts.go` 文件中被定义为 +`context.Background()`。这个上下文贯穿整个应用的生命周期,用于传递追踪信息和控制取消信号。 -Span 的生命周期管理在 `internal/otelTrace/span.go` 文件中实现。`Span()` 函数是创建新 Span 的主要方法,它接受一个父上下文、追踪名称和 Span 名称,并返回一个新的上下文和 Span 对象。该函数内部使用 `otel.Tracer(traceName).Start()` 来启动一个 Span,并自动添加了通用属性,如 `tracer.name` 和 `span.kind`,以优化指标收集。 +Span 的生命周期管理在 `internal/otelTrace/span.go` 文件中实现。`Span()` 函数是创建新 Span 的主要方法,它接受一个父上下文、追踪名称和 +Span 名称,并返回一个新的上下文和 Span 对象。该函数内部使用 `otel.Tracer(traceName).Start()` 来启动一个 Span,并自动添加了通用属性,如 +`tracer.name` 和 `span.kind`,以优化指标收集。 -对于异步操作,系统提供了 `CreateLinkContext` 和 `CreateAsyncContext` 等函数。这些函数创建的上下文与父 Span 保持关联(通过 `trace.WithLinks`),但不继承父上下文的取消信号。这确保了异步任务(如后台处理)可以独立完成,不会因为父请求的取消而中断,同时又能将追踪信息链接到原始请求链路中。 +对于异步操作,系统提供了 `CreateLinkContext` 和 `CreateAsyncContext` 等函数。这些函数创建的上下文与父 Span 保持关联(通过 +`trace.WithLinks`),但不继承父上下文的取消信号。这确保了异步任务(如后台处理)可以独立完成,不会因为父请求的取消而中断,同时又能将追踪信息链接到原始请求链路中。 ```mermaid classDiagram @@ -82,17 +92,22 @@ SpanManager --> Span : 创建和管理 ``` **Diagram sources** + - [internal/otelTrace/span.go](file://internal/otelTrace/span.go#L1-L151) **Section sources** + - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L11-L11) - [internal/otelTrace/span.go](file://internal/otelTrace/span.go#L1-L151) ## 日志与追踪上下文关联 -为了实现日志与追踪的上下文关联,kami_gateway 实现了一个自定义的 `CustomLogger` 结构体。该结构体在 `internal/otelTrace/logs.go` 文件中定义,包装了 `zap.Logger`,并提供了一个 `WithContext(ctx context.Context)` 方法。 +为了实现日志与追踪的上下文关联,kami_gateway 实现了一个自定义的 `CustomLogger` 结构体。该结构体在 +`internal/otelTrace/logs.go` 文件中定义,包装了 `zap.Logger`,并提供了一个 `WithContext(ctx context.Context)` 方法。 -当调用 `WithContext` 方法时,它会检查传入的上下文。如果上下文有效且包含一个有效的 Span,则会将该上下文作为 `zap.Reflect("ctx", ctx)` 添加到日志记录器中。这样,当一条日志被记录时,它就携带了当前的追踪上下文(包括 Trace ID 和 Span ID),使得在日志系统中可以轻松地通过 Trace ID 关联到完整的调用链路。 +当调用 `WithContext` 方法时,它会检查传入的上下文。如果上下文有效且包含一个有效的 Span,则会将该上下文作为 +`zap.Reflect("ctx", ctx)` 添加到日志记录器中。这样,当一条日志被记录时,它就携带了当前的追踪上下文(包括 Trace ID 和 Span +ID),使得在日志系统中可以轻松地通过 Trace ID 关联到完整的调用链路。 ```mermaid flowchart TD @@ -108,16 +123,22 @@ G --> H[日志包含 Trace ID/Span ID] ``` **Diagram sources** + - [internal/otelTrace/logs.go](file://internal/otelTrace/logs.go#L1-L29) **Section sources** + - [internal/otelTrace/logs.go](file://internal/otelTrace/logs.go#L1-L29) ## Beego HTTP服务集成 -OpenTelemetry 通过中间件(Middleware)的方式集成到 Beego 的 HTTP 服务中。`internal/otelTrace/middleware.go` 文件中的 `Middleware` 函数是一个 Beego 过滤器,它在每个 HTTP 请求处理前被调用。 +OpenTelemetry 通过中间件(Middleware)的方式集成到 Beego 的 HTTP 服务中。`internal/otelTrace/middleware.go` 文件中的 +`Middleware` 函数是一个 Beego 过滤器,它在每个 HTTP 请求处理前被调用。 -该中间件首先从 HTTP 请求头中提取上游服务传递的追踪上下文(如 `traceparent` 头),确保了分布式调用链路的连续性。然后,它使用 `otel.Tracer("gateway-router").Start()` 创建一个新的服务器端 Span,并设置了一系列关键属性,包括 HTTP 方法、URL、状态码、客户端 IP 等。为了保护业务逻辑不受追踪系统故障的影响,中间件还集成了一个熔断器(Circuit Breaker),当追踪导出器连续失败达到阈值时,会自动开启熔断,绕过追踪逻辑,确保业务请求的正常处理。 +该中间件首先从 HTTP 请求头中提取上游服务传递的追踪上下文(如 `traceparent` 头),确保了分布式调用链路的连续性。然后,它使用 +`otel.Tracer("gateway-router").Start()` 创建一个新的服务器端 Span,并设置了一系列关键属性,包括 HTTP 方法、URL、状态码、客户端 +IP 等。为了保护业务逻辑不受追踪系统故障的影响,中间件还集成了一个熔断器(Circuit +Breaker),当追踪导出器连续失败达到阈值时,会自动开启熔断,绕过追踪逻辑,确保业务请求的正常处理。 ```mermaid sequenceDiagram @@ -138,39 +159,49 @@ Beego-->>Client : 返回HTTP响应 ``` **Diagram sources** + - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) **Section sources** + - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) ## 资源释放与清理机制 -在 `main.go` 文件中,`otelTrace.InitTracer()` 的返回值被赋值给 `cleanup1`, `cleanup2`, `cleanup3` 三个函数。这些函数分别对应追踪、指标和日志导出器的 `Shutdown` 方法。 +在 `main.go` 文件中,`otelTrace.InitTracer()` 的返回值被赋值给 `cleanup1`, `cleanup2`, `cleanup3` +三个函数。这些函数分别对应追踪、指标和日志导出器的 `Shutdown` 方法。 -通过 `defer` 语句,这些清理函数被注册为程序退出时执行。当 `main()` 函数执行完毕或程序因异常退出时,`defer` 会确保这些清理函数被调用。`Shutdown` 方法会优雅地关闭导出器,将内存中尚未导出的缓冲数据(如队列中的 Span)刷新到后端收集器,然后断开与收集器的连接。这种机制保证了在程序终止前,所有已生成的追踪数据都能被完整地发送出去,避免了数据丢失。 +通过 `defer` 语句,这些清理函数被注册为程序退出时执行。当 `main()` 函数执行完毕或程序因异常退出时,`defer` 会确保这些清理函数被调用。 +`Shutdown` 方法会优雅地关闭导出器,将内存中尚未导出的缓冲数据(如队列中的 +Span)刷新到后端收集器,然后断开与收集器的连接。这种机制保证了在程序终止前,所有已生成的追踪数据都能被完整地发送出去,避免了数据丢失。 **Section sources** + - [main.go](file://main.go#L1-L58) ## OTLP导出与采样策略 kami_gateway 使用 OTLP/gRPC 协议将数据导出到位于 `38.38.251.113:31547` 的收集器。为了优化性能和资源使用,系统配置了多项生产环境策略: -* **批量导出 (Batch Export):** 使用 `sdktrace.NewBatchSpanProcessor` 将多个 Span 批量发送。配置了 5 秒的批量发送间隔 (`BatchTimeout`) 和 512 条的最大批量大小 (`MaxExportBatchSize`),平衡了实时性和网络开销。 -* **采样策略 (Sampling):** 采用基于 Trace ID 比例的采样策略 (`traceIDRatioBased`),默认采样率为 10% (`DefaultSamplingRatio`)。这在保证可观测性的同时,有效控制了高负载下的数据量和系统开销。 -* **熔断保护 (Circuit Breaker):** 在 `internal/otelTrace/circuit_breaker.go` 中实现了一个简单的熔断器。当导出失败次数达到阈值(默认5次)时,熔断器会开启,暂时停止导出操作,防止因后端收集器故障导致应用资源耗尽。 -* **资源限制:** 配置了最大队列大小 (`MaxQueueSize=2048`) 和最大并发导出数,防止内存溢出。 +* **批量导出 (Batch Export):** 使用 `sdktrace.NewBatchSpanProcessor` 将多个 Span 批量发送。配置了 5 秒的批量发送间隔 ( + `BatchTimeout`) 和 512 条的最大批量大小 (`MaxExportBatchSize`),平衡了实时性和网络开销。 +* **采样策略 (Sampling):** 采用基于 Trace ID 比例的采样策略 (`traceIDRatioBased`),默认采样率为 10% ( + `DefaultSamplingRatio`)。这在保证可观测性的同时,有效控制了高负载下的数据量和系统开销。 +* **熔断保护 (Circuit Breaker):** 在 `internal/otelTrace/circuit_breaker.go` + 中实现了一个简单的熔断器。当导出失败次数达到阈值(默认5次)时,熔断器会开启,暂时停止导出操作,防止因后端收集器故障导致应用资源耗尽。 +* **资源限制:** 配置了最大队列大小 (`MaxQueueSize=2048`) 和最大并发导出数,防止内存溢出。 **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L29-L205) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L55) - [internal/otelTrace/circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L1-L50) ## 链路追踪调试最佳实践 -1. **检查初始化:** 确保 `otelTrace.InitTracer()` 在 `main()` 函数早期被成功调用,并且返回的清理函数被正确注册。 -2. **验证中间件:** 确认 Beego 的路由配置中已注册 `otelTrace.Middleware`,否则 HTTP 请求将无法被追踪。 -3. **分析日志:** 利用 `CustomLogger.WithContext()` 记录的日志,通过 `ctx` 字段中的 Trace ID 在日志系统中搜索,可以快速定位到与特定请求相关的所有日志。 -4. **监控导出器健康:** 关注 `monitorExporterHealth` goroutine 的输出,它会监控导出器的健康状态。如果发现大量导出失败,应检查网络连接和收集器状态。 -5. **利用熔断器:** 在生产环境中,熔断器是保护系统稳定的关键。如果发现追踪数据突然中断,应首先检查熔断器是否已开启,并排查后端收集器的问题。 -6. **调整采样率:** 在调试阶段,可以临时提高采样率以获取更完整的数据;在生产环境稳定后,应恢复到较低的采样率以控制成本。 \ No newline at end of file +1. **检查初始化:** 确保 `otelTrace.InitTracer()` 在 `main()` 函数早期被成功调用,并且返回的清理函数被正确注册。 +2. **验证中间件:** 确认 Beego 的路由配置中已注册 `otelTrace.Middleware`,否则 HTTP 请求将无法被追踪。 +3. **分析日志:** 利用 `CustomLogger.WithContext()` 记录的日志,通过 `ctx` 字段中的 Trace ID 在日志系统中搜索,可以快速定位到与特定请求相关的所有日志。 +4. **监控导出器健康:** 关注 `monitorExporterHealth` goroutine 的输出,它会监控导出器的健康状态。如果发现大量导出失败,应检查网络连接和收集器状态。 +5. **利用熔断器:** 在生产环境中,熔断器是保护系统稳定的关键。如果发现追踪数据突然中断,应首先检查熔断器是否已开启,并排查后端收集器的问题。 +6. **调整采样率:** 在调试阶段,可以临时提高采样率以获取更完整的数据;在生产环境稳定后,应恢复到较低的采样率以控制成本。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/Span生命周期管理.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/Span生命周期管理.md index 0e5abc8..33a0665 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/Span生命周期管理.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/Span生命周期管理.md @@ -13,6 +13,7 @@ # Span生命周期管理 ## Table of Contents + 1. [引言](#引言) 2. [核心Span管理函数](#核心span管理函数) 3. [异步与可追踪上下文](#异步与可追踪上下文) @@ -22,9 +23,12 @@ ## 引言 -在 `kami_gateway` 系统中,OpenTelemetry (OTel) 被用于实现全面的分布式追踪。`internal/otelTrace` 包提供了对 OTel API 的封装和扩展,旨在简化开发者在创建、关联和管理追踪 Span 时的操作。本文档将深入解析该包中关于 Span 生命周期管理的核心机制,包括 `Span()` 辅助函数、`CreateAsyncContext()`、`CreateTraceableContext()` 等关键函数的设计意图与实现细节,并结合订单处理、渠道调用等业务代码,展示其在实际场景中的应用模式。 +在 `kami_gateway` 系统中,OpenTelemetry (OTel) 被用于实现全面的分布式追踪。`internal/otelTrace` 包提供了对 OTel API +的封装和扩展,旨在简化开发者在创建、关联和管理追踪 Span 时的操作。本文档将深入解析该包中关于 Span 生命周期管理的核心机制,包括 +`Span()` 辅助函数、`CreateAsyncContext()`、`CreateTraceableContext()` 等关键函数的设计意图与实现细节,并结合订单处理、渠道调用等业务代码,展示其在实际场景中的应用模式。 **Section sources** + - [span.go](file://internal/otelTrace/span.go#L13-L129) ## 核心Span管理函数 @@ -33,22 +37,32 @@ `Span()` 函数是创建追踪 Span 的核心入口,它封装了 `otel.Tracer().Start()` 的调用,并自动注入了通用的追踪属性,极大地简化了开发者的使用。 -该函数通过 `trace.WithAttributes()` 选项,为所有创建的 Span 统一添加了 `tracer.name` 和 `span.kind` 两个关键属性。其中,`tracer.name` 的值由调用者传入,用于标识追踪的来源;`span.kind` 固定为 `"internal"`,表明这是一个内部处理的 Span。这种设计确保了追踪数据的一致性和可读性,便于在监控系统中进行聚合分析。 +该函数通过 `trace.WithAttributes()` 选项,为所有创建的 Span 统一添加了 `tracer.name` 和 `span.kind` 两个关键属性。其中, +`tracer.name` 的值由调用者传入,用于标识追踪的来源;`span.kind` 固定为 `"internal"`,表明这是一个内部处理的 +Span。这种设计确保了追踪数据的一致性和可读性,便于在监控系统中进行聚合分析。 -此外,函数还包含了一个安全检查,当传入的 `ctx` 为 `nil` 时,会自动创建一个 `context.Background()`,以避免程序因空上下文而 panic。 +此外,函数还包含了一个安全检查,当传入的 `ctx` 为 `nil` 时,会自动创建一个 `context.Background()`,以避免程序因空上下文而 +panic。 **Section sources** + - [span.go](file://internal/otelTrace/span.go#L13-L30) ## 异步与可追踪上下文 ### CreateLinkContext() 与关联关系 -`CreateLinkContext()` 函数的设计核心在于创建一种“关联关系”(Linked Relationship),而非传统的“父子关系”(Parent-Child Relationship)。在标准的上下文传播中,父 Context 的取消会通过 `context.WithCancel` 等机制传播到所有子 Context,导致所有关联的 Goroutine 被强制终止。 +`CreateLinkContext()` 函数的设计核心在于创建一种“关联关系”(Linked Relationship),而非传统的“父子关系”(Parent-Child +Relationship)。在标准的上下文传播中,父 Context 的取消会通过 `context.WithCancel` 等机制传播到所有子 Context,导致所有关联的 +Goroutine 被强制终止。 -`CreateLinkContext()` 通过 `trace.ContextWithSpanContext(context.Background(), parentSpanCtx)` 创建了一个新的、独立于父 Context 生命周期的上下文。它使用 `context.Background()` 作为新上下文的根,从而切断了取消信号的传播链。同时,它通过 `trace.WithLinks()` 选项,将新创建的 Span 与父 Span 的 `SpanContext` 进行链接。这使得在追踪系统中,我们仍然可以看到这两个 Span 之间的关联,但它们的执行是独立的。 +`CreateLinkContext()` 通过 `trace.ContextWithSpanContext(context.Background(), parentSpanCtx)` 创建了一个新的、独立于父 +Context 生命周期的上下文。它使用 `context.Background()` 作为新上下文的根,从而切断了取消信号的传播链。同时,它通过 +`trace.WithLinks()` 选项,将新创建的 Span 与父 Span 的 `SpanContext` 进行链接。这使得在追踪系统中,我们仍然可以看到这两个 +Span 之间的关联,但它们的执行是独立的。 **Diagram sources** + - [span.go](file://internal/otelTrace/span.go#L42-L57) ```mermaid @@ -64,45 +78,57 @@ note right of E: 生命周期独立
不继承取消信号 ### CreateAsyncContext() -`CreateAsyncContext()` 是 `CreateLinkContext()` 的一个特化版本,专门用于处理异步任务(如 Goroutine)。它在调用 `CreateLinkContext()` 的基础上,进一步添加了 `async.operation`、`async.type` 和 `relationship` 等属性,明确标识了这是一个异步操作,并且与父 Span 是关联关系。 +`CreateAsyncContext()` 是 `CreateLinkContext()` 的一个特化版本,专门用于处理异步任务(如 Goroutine)。它在调用 +`CreateLinkContext()` 的基础上,进一步添加了 `async.operation`、`async.type` 和 `relationship` 等属性,明确标识了这是一个异步操作,并且与父 +Span 是关联关系。 -这种设计模式在处理后台任务时非常有用,例如,当一个订单请求需要异步调用第三方渠道进行处理时,即使用户的 HTTP 请求已经超时或被取消,后台的渠道调用任务仍能独立完成,确保业务逻辑的完整性。 +这种设计模式在处理后台任务时非常有用,例如,当一个订单请求需要异步调用第三方渠道进行处理时,即使用户的 HTTP +请求已经超时或被取消,后台的渠道调用任务仍能独立完成,确保业务逻辑的完整性。 **Section sources** + - [span.go](file://internal/otelTrace/span.go#L61-L69) ### CreateTraceableContext() -`CreateTraceableContext()` 函数旨在创建一个“可追踪的上下文”,它不仅保持了与父 Span 的关联,还通过 `trace.WithAttributes()` 传递了更丰富的追踪信息,如 `parent.trace_id`、`parent.span_id` 等。这使得在复杂的分布式系统中,即使经过多层异步调用,也能完整地追溯到原始请求的链路。 +`CreateTraceableContext()` 函数旨在创建一个“可追踪的上下文”,它不仅保持了与父 Span 的关联,还通过 `trace.WithAttributes()` +传递了更丰富的追踪信息,如 `parent.trace_id`、`parent.span_id` 等。这使得在复杂的分布式系统中,即使经过多层异步调用,也能完整地追溯到原始请求的链路。 此函数同样使用 `context.Background()` 作为新上下文的根,保证了生命周期的独立性,同时通过链接和属性注入,实现了追踪链路的完整传递。 **Section sources** + - [span.go](file://internal/otelTrace/span.go#L73-L93) ## 状态与属性管理 ### SetSpanError() 与 SetSpanSuccess() -`SetSpanError()` 和 `SetSpanSuccess()` 函数提供了标准化的错误和成功状态标记方法。`SetSpanError()` 会将 Span 的状态码设置为 `codes.Error`,并添加 `error.message` 和 `error.type` 属性。`SetSpanSuccess()` 则将状态码设置为 `codes.Ok`,并添加 `operation.status` 属性。 +`SetSpanError()` 和 `SetSpanSuccess()` 函数提供了标准化的错误和成功状态标记方法。`SetSpanError()` 会将 Span 的状态码设置为 +`codes.Error`,并添加 `error.message` 和 `error.type` 属性。`SetSpanSuccess()` 则将状态码设置为 `codes.Ok`,并添加 +`operation.status` 属性。 这种标准化的处理方式,使得在追踪系统中可以轻松地根据这些预定义的属性进行错误率统计、成功率分析等监控操作,而无需在每个业务代码中重复编写类似的逻辑。 **Section sources** + - [span.go](file://internal/otelTrace/span.go#L96-L120) ### AddSpanAttributes() -`AddSpanAttributes()` 函数提供了一个便捷的接口,用于向 Span 添加自定义属性。它直接调用了 `span.SetAttributes()`,并处理了 `span` 为 `nil` 的边界情况。开发者可以利用此函数轻松地将业务相关的上下文信息(如订单号、用户ID等)注入到追踪数据中,极大地增强了追踪信息的诊断价值。 +`AddSpanAttributes()` 函数提供了一个便捷的接口,用于向 Span 添加自定义属性。它直接调用了 `span.SetAttributes()`,并处理了 +`span` 为 `nil` 的边界情况。开发者可以利用此函数轻松地将业务相关的上下文信息(如订单号、用户ID等)注入到追踪数据中,极大地增强了追踪信息的诊断价值。 **Section sources** + - [span.go](file://internal/otelTrace/span.go#L123-L129) ## 业务场景中的应用 ### 订单池匹配中的异步处理 -在订单池服务 `OrderPoolServiceImpl.matchOrdersForFaceValue` 中,为了处理高并发的订单匹配,系统使用了 Goroutine 来并行处理不同面值的订单。在此场景下,`CreateAsyncContext()` 被用来创建独立的追踪上下文。 +在订单池服务 `OrderPoolServiceImpl.matchOrdersForFaceValue` 中,为了处理高并发的订单匹配,系统使用了 Goroutine +来并行处理不同面值的订单。在此场景下,`CreateAsyncContext()` 被用来创建独立的追踪上下文。 ```go func (s *OrderPoolServiceImpl) matchOrdersForFaceValue(ctx context.Context, channel card_sender.SendCardTaskEnum, roadUid string, faceValue float64) { @@ -115,11 +141,13 @@ func (s *OrderPoolServiceImpl) matchOrdersForFaceValue(ctx context.Context, chan 这确保了即使主订单处理流程被取消,正在进行的订单匹配任务仍能继续执行,避免了因上游请求取消而导致的业务中断。 **Section sources** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L336-L526) ### 队列任务处理中的追踪 -在队列系统 `QueueManager.EnqueueTask` 中,当一个任务被加入队列时,会创建一个 Span 来追踪 `EnqueueTask` 操作。而在 `RedisQueue.processQueue` 方法中,为了处理队列中的任务,系统使用 `CreateAsyncContext` 创建了一个新的上下文来处理每个任务。 +在队列系统 `QueueManager.EnqueueTask` 中,当一个任务被加入队列时,会创建一个 Span 来追踪 `EnqueueTask` 操作。而在 +`RedisQueue.processQueue` 方法中,为了处理队列中的任务,系统使用 `CreateAsyncContext` 创建了一个新的上下文来处理每个任务。 ```go func (q *RedisQueue) processQueue(ctx context.Context) { @@ -135,18 +163,26 @@ func (q *RedisQueue) processQueue(ctx context.Context) { 这种方式将队列的消费过程与生产过程在追踪链路上关联起来,同时保证了任务处理的独立性,是典型的异步任务追踪模式。 **Section sources** + - [queue.go](file://internal/service/supplier/third_party/queue/queue.go#L380-L400) ### 渠道调用中的复杂追踪 -在 `BatchSixChannelHandler.SubmitCard` 和 `SendCardTaskTypeFatSix.HandleSendCardTask` 等渠道调用的实现中,`Span()` 函数被广泛用于创建追踪 Span。这些 Span 会携带 `channelCode`、`faceValue`、`cardNo` 等关键业务参数作为属性,使得在排查渠道调用失败问题时,能够快速定位到具体的调用实例。 +在 `BatchSixChannelHandler.SubmitCard` 和 `SendCardTaskTypeFatSix.HandleSendCardTask` 等渠道调用的实现中,`Span()` +函数被广泛用于创建追踪 Span。这些 Span 会携带 `channelCode`、`faceValue`、`cardNo` +等关键业务参数作为属性,使得在排查渠道调用失败问题时,能够快速定位到具体的调用实例。 -例如,在 `SendCardTaskTypeFatSix.HandleSendCardTask` 中,Span 被用来追踪整个提交卡密的复杂流程,包括获取代理、识别验证码、提交数据等步骤,并通过 `span.AddEvent()` 记录关键事件点,为性能分析和故障排查提供了详尽的数据。 +例如,在 `SendCardTaskTypeFatSix.HandleSendCardTask` 中,Span 被用来追踪整个提交卡密的复杂流程,包括获取代理、识别验证码、提交数据等步骤,并通过 +`span.AddEvent()` 记录关键事件点,为性能分析和故障排查提供了详尽的数据。 **Section sources** + - [batch_six_handler.go](file://internal/service/supplier/third_party/queue/channel/batch_six_handler.go#L105-L212) - [fat_six.go](file://internal/service/supplier/third_party/pool/card_sender/fat_six.go#L156-L307) ## 总结 -`kami_gateway` 的 OTel 追踪系统通过精心设计的辅助函数,有效地解决了分布式系统中 Span 的创建、关联与管理问题。`Span()` 函数简化了基础 Span 的创建;`CreateAsyncContext()` 和 `CreateTraceableContext()` 通过“关联关系”模式,巧妙地平衡了追踪链路的完整性与异步任务的独立性;`SetSpanError()`、`SetSpanSuccess()` 和 `AddSpanAttributes()` 则提供了标准化的状态和属性管理接口。这些机制在订单处理、渠道调用等核心业务场景中得到了广泛应用,为系统的可观测性奠定了坚实的基础。 \ No newline at end of file +`kami_gateway` 的 OTel 追踪系统通过精心设计的辅助函数,有效地解决了分布式系统中 Span 的创建、关联与管理问题。`Span()` +函数简化了基础 Span 的创建;`CreateAsyncContext()` 和 `CreateTraceableContext()` 通过“关联关系”模式,巧妙地平衡了追踪链路的完整性与异步任务的独立性; +`SetSpanError()`、`SetSpanSuccess()` 和 `AddSpanAttributes()` +则提供了标准化的状态和属性管理接口。这些机制在订单处理、渠道调用等核心业务场景中得到了广泛应用,为系统的可观测性奠定了坚实的基础。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/分布式上下文传播.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/分布式上下文传播.md index fcd3f2e..6c7c90b 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/分布式上下文传播.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/分布式上下文传播.md @@ -8,6 +8,7 @@ ## 目录 + 1. [引言](#引言) 2. [上下文传播机制配置](#上下文传播机制配置) 3. [W3C Trace Context 传播](#w3c-trace-context-传播) @@ -16,13 +17,19 @@ 6. [结论](#结论) ## 引言 -kami_gateway 系统通过 OpenTelemetry 实现了完整的分布式追踪能力,其中上下文传播机制是确保跨服务调用链路连续性的核心。本系统通过配置复合文本映射传播器,集成了 W3C Trace Context 和 W3C Baggage 两种标准,实现了调用链路追踪和业务上下文数据的跨服务传递。在支付网关的多通道调用场景中,这一机制确保了从订单调度到代付处理的全链路追踪完整性,为系统监控、故障排查和性能优化提供了坚实基础。 + +kami_gateway 系统通过 OpenTelemetry 实现了完整的分布式追踪能力,其中上下文传播机制是确保跨服务调用链路连续性的核心。本系统通过配置复合文本映射传播器,集成了 +W3C Trace Context 和 W3C Baggage +两种标准,实现了调用链路追踪和业务上下文数据的跨服务传递。在支付网关的多通道调用场景中,这一机制确保了从订单调度到代付处理的全链路追踪完整性,为系统监控、故障排查和性能优化提供了坚实基础。 ## 上下文传播机制配置 -kami_gateway 系统在初始化阶段通过 `otel.SetTextMapPropagator` 配置了复合文本映射传播器,该传播器集成了 W3C Trace Context 和 W3C Baggage 两种标准。这种配置确保了系统能够同时处理追踪上下文和业务上下文的传播需求。 +kami_gateway 系统在初始化阶段通过 `otel.SetTextMapPropagator` 配置了复合文本映射传播器,该传播器集成了 W3C Trace Context +和 W3C Baggage 两种标准。这种配置确保了系统能够同时处理追踪上下文和业务上下文的传播需求。 -在 `internal/otelTrace/init.go` 文件中,系统通过 `propagation.NewCompositeTextMapPropagator` 创建了一个复合传播器,将 `propagation.TraceContext{}` 和 `propagation.Baggage{}` 两种传播器组合在一起。这种设计允许系统在单个 HTTP 请求中同时传播追踪信息和业务数据,实现了功能的解耦和复用。 +在 `internal/otelTrace/init.go` 文件中,系统通过 `propagation.NewCompositeTextMapPropagator` 创建了一个复合传播器,将 +`propagation.TraceContext{}` 和 `propagation.Baggage{}` 两种传播器组合在一起。这种设计允许系统在单个 HTTP +请求中同时传播追踪信息和业务数据,实现了功能的解耦和复用。 ```mermaid graph TD @@ -35,16 +42,21 @@ D --> G[业务上下文数据] ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L150-L153) **Section sources** + - [init.go](file://internal/otelTrace/init.go#L150-L153) ## W3C Trace Context 传播 -W3C Trace Context 标准通过 `traceparent` 和 `tracestate` HTTP 头在服务间传递追踪上下文,确保调用链的连续性。在 kami_gateway 系统中,这一机制通过中间件在请求处理的各个阶段被激活和维护。 +W3C Trace Context 标准通过 `traceparent` 和 `tracestate` HTTP 头在服务间传递追踪上下文,确保调用链的连续性。在 +kami_gateway 系统中,这一机制通过中间件在请求处理的各个阶段被激活和维护。 -当 HTTP 请求到达网关时,`internal/otelTrace/middleware.go` 中的 `Middleware` 函数会从请求头中提取上游的 trace context。通过 `otel.GetTextMapPropagator()` 获取配置的传播器,并使用 `propagator.Extract` 方法从请求头中提取上下文信息。这一过程确保了即使在复杂的微服务架构中,每个服务实例也能正确地继承和延续调用链。 +当 HTTP 请求到达网关时,`internal/otelTrace/middleware.go` 中的 `Middleware` 函数会从请求头中提取上游的 trace context。通过 +`otel.GetTextMapPropagator()` 获取配置的传播器,并使用 `propagator.Extract` +方法从请求头中提取上下文信息。这一过程确保了即使在复杂的微服务架构中,每个服务实例也能正确地继承和延续调用链。 ```mermaid sequenceDiagram @@ -59,27 +71,36 @@ Gateway->>Client : 响应 ``` **Diagram sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L30-L33) **Section sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L30-L33) ## W3C Baggage 传播 -W3C Baggage 标准允许在服务间传递业务相关的上下文数据,这些数据可以包含商户信息、订单属性、风险控制参数等业务关键信息。在 kami_gateway 系统中,Baggage 传播机制为跨服务的业务逻辑处理提供了必要的上下文支持。 +W3C Baggage 标准允许在服务间传递业务相关的上下文数据,这些数据可以包含商户信息、订单属性、风险控制参数等业务关键信息。在 +kami_gateway 系统中,Baggage 传播机制为跨服务的业务逻辑处理提供了必要的上下文支持。 -虽然代码中没有直接展示 Baggage 的具体使用,但通过配置 `propagation.Baggage{}` 作为复合传播器的一部分,系统具备了处理业务上下文数据的能力。在实际应用中,这些数据可以用于实现基于上下文的路由决策、风险控制策略应用和个性化服务处理。 +虽然代码中没有直接展示 Baggage 的具体使用,但通过配置 `propagation.Baggage{}` +作为复合传播器的一部分,系统具备了处理业务上下文数据的能力。在实际应用中,这些数据可以用于实现基于上下文的路由决策、风险控制策略应用和个性化服务处理。 -在支付网关的场景中,Baggage 可以携带如商户等级、风险评分、特殊处理要求等信息,确保下游服务能够根据这些上下文做出正确的业务决策。例如,在订单调度过程中,可以根据 Baggage 中携带的商户优先级信息,优先选择高优先级商户的支付通道。 +在支付网关的场景中,Baggage 可以携带如商户等级、风险评分、特殊处理要求等信息,确保下游服务能够根据这些上下文做出正确的业务决策。例如,在订单调度过程中,可以根据 +Baggage 中携带的商户优先级信息,优先选择高优先级商户的支付通道。 **Section sources** + - [init.go](file://internal/otelTrace/init.go#L152) ## 支付网关场景应用 -在支付网关的多通道调用场景中,上下文传播机制在订单调度和代付处理等关键流程中发挥着重要作用。以 `internal/controllers/order_controller.go` 中的 `OrderSchedule` 方法为例,当商户请求重新调度订单时,系统需要确保从接收请求到最终调用第三方供应商的整个流程中,追踪上下文保持连续。 +在支付网关的多通道调用场景中,上下文传播机制在订单调度和代付处理等关键流程中发挥着重要作用。以 +`internal/controllers/order_controller.go` 中的 `OrderSchedule` +方法为例,当商户请求重新调度订单时,系统需要确保从接收请求到最终调用第三方供应商的整个流程中,追踪上下文保持连续。 -在 `internal/service/pay_solve.go` 文件中,`SolvePaySuccess` 和 `SolvePayFail` 方法处理支付成功和失败的后续操作。这些方法通过 `ctx` 参数接收并传递上下文信息,确保在异步通知、账户更新等操作中,追踪信息能够正确关联到原始请求。 +在 `internal/service/pay_solve.go` 文件中,`SolvePaySuccess` 和 `SolvePayFail` 方法处理支付成功和失败的后续操作。这些方法通过 +`ctx` 参数接收并传递上下文信息,确保在异步通知、账户更新等操作中,追踪信息能够正确关联到原始请求。 ```mermaid flowchart TD @@ -96,12 +117,16 @@ G --> K[发送失败通知] ``` **Diagram sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L30-L75) - [pay_solve.go](file://internal/service/pay_solve.go#L10-L100) **Section sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L30-L75) - [pay_solve.go](file://internal/service/pay_solve.go#L10-L100) ## 结论 -kami_gateway 系统通过精心设计的上下文传播机制,实现了 W3C Trace Context 和 W3C Baggage 标准的集成应用。这一机制不仅确保了全链路追踪的完整性,还为跨服务的业务上下文传递提供了支持。在支付网关的实际应用中,该机制有效支持了订单调度、代付处理等复杂业务流程的监控和管理,为系统的稳定运行和持续优化提供了重要保障。 \ No newline at end of file + +kami_gateway 系统通过精心设计的上下文传播机制,实现了 W3C Trace Context 和 W3C Baggage +标准的集成应用。这一机制不仅确保了全链路追踪的完整性,还为跨服务的业务上下文传递提供了支持。在支付网关的实际应用中,该机制有效支持了订单调度、代付处理等复杂业务流程的监控和管理,为系统的稳定运行和持续优化提供了重要保障。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/初始化与资源配置.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/初始化与资源配置.md index 9b4659f..8fdfc79 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/初始化与资源配置.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/初始化与资源配置.md @@ -8,6 +8,7 @@ ## 目录 + 1. [OpenTelemetry 初始化机制](#opentelemetry-初始化机制) 2. [OTLP 协议连接与网络优化](#otlp-协议连接与网络优化) 3. [资源对象与上下文标识](#资源对象与上下文标识) @@ -17,23 +18,29 @@ ## OpenTelemetry 初始化机制 -`kami_gateway` 项目通过 `otelTrace.InitTracer()` 函数实现 OpenTelemetry 的全面初始化。该函数不仅负责追踪(Tracing)功能的启动,还同时初始化了指标(Metrics)和日志(Logs)的导出,构建了一个完整的可观测性(Observability)体系。此初始化过程是整个网关服务可观测性的基石,确保了所有运行时数据能够被有效收集和分析。 +`kami_gateway` 项目通过 `otelTrace.InitTracer()` 函数实现 OpenTelemetry +的全面初始化。该函数不仅负责追踪(Tracing)功能的启动,还同时初始化了指标(Metrics)和日志(Logs)的导出,构建了一个完整的可观测性(Observability)体系。此初始化过程是整个网关服务可观测性的基石,确保了所有运行时数据能够被有效收集和分析。 **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L29-L205) ## OTLP 协议连接与网络优化 `InitTracer()` 函数通过 OTLP (OpenTelemetry Protocol) 协议连接到后端的 OpenTelemetry 收集器(Collector)。其核心配置如下: -1. **非安全模式连接 (Insecure Mode)**:通过 `otlptracegrpc.WithInsecure()` 配置,使用明文 gRPC 连接。这适用于内部网络或已通过其他方式(如 VPC、服务网格)保障安全的环境,避免了 TLS 握手的性能开销。 -2. **超时设置 (Timeout)**:通过 `otlptracegrpc.WithTimeout(DefaultTimeout)` 设置了 5 秒的超时时间。该值在 `consts.go` 文件中定义为 `DefaultTimeout = 5 * time.Second`,旨在避免因网络延迟或收集器故障导致的应用程序长时间阻塞。 -3. **网络传输优化**: - * **Gzip 压缩**:通过 `otlptracegrpc.WithCompressor("gzip")` 启用 Gzip 压缩,显著减少了网络传输的数据量,降低了带宽消耗和传输延迟。 - * **重试机制**:配置了指数退避重试策略(`WithRetry`),初始重试间隔为 1 秒,最大为 10 秒,总重试时间不超过 30 秒,增强了在短暂网络抖动下的鲁棒性。 - * **批量处理**:使用 `sdktrace.NewBatchSpanProcessor` 将多个追踪片段(Span)批量导出,减少了与收集器的连接次数,提升了整体性能。 +1. **非安全模式连接 (Insecure Mode)**:通过 `otlptracegrpc.WithInsecure()` 配置,使用明文 gRPC 连接。这适用于内部网络或已通过其他方式(如 + VPC、服务网格)保障安全的环境,避免了 TLS 握手的性能开销。 +2. **超时设置 (Timeout)**:通过 `otlptracegrpc.WithTimeout(DefaultTimeout)` 设置了 5 秒的超时时间。该值在 `consts.go` + 文件中定义为 `DefaultTimeout = 5 * time.Second`,旨在避免因网络延迟或收集器故障导致的应用程序长时间阻塞。 +3. **网络传输优化**: + * **Gzip 压缩**:通过 `otlptracegrpc.WithCompressor("gzip")` 启用 Gzip 压缩,显著减少了网络传输的数据量,降低了带宽消耗和传输延迟。 + * **重试机制**:配置了指数退避重试策略(`WithRetry`),初始重试间隔为 1 秒,最大为 10 秒,总重试时间不超过 30 + 秒,增强了在短暂网络抖动下的鲁棒性。 + * **批量处理**:使用 `sdktrace.NewBatchSpanProcessor` 将多个追踪片段(Span)批量导出,减少了与收集器的连接次数,提升了整体性能。 **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L32-L54) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L14-L18) @@ -41,9 +48,9 @@ 为了确保追踪数据具备正确的上下文信息,`InitTracer()` 函数创建了一个 `Resource` 对象,并通过 `attribute.String` 设置了关键的标识属性: -* **服务名称 (service.name)**:从环境变量 `serverName` 中读取,确保每个服务实例都有唯一的标识。 -* **部署环境 (deployment.environment)**:从环境变量 `ENVIRONMENT` 中读取,用于区分开发、测试、生产等不同环境的追踪数据。 -* **语言类型 (library.language)**:固定为 `go`,标识了服务的开发语言。 +* **服务名称 (service.name)**:从环境变量 `serverName` 中读取,确保每个服务实例都有唯一的标识。 +* **部署环境 (deployment.environment)**:从环境变量 `ENVIRONMENT` 中读取,用于区分开发、测试、生产等不同环境的追踪数据。 +* **语言类型 (library.language)**:固定为 `go`,标识了服务的开发语言。 这些属性作为追踪数据的元数据,使得在后端分析系统(如 Jaeger、Zipkin)中能够方便地对数据进行过滤、聚合和分析。 @@ -58,27 +65,33 @@ F --> G["返回 Shutdown 函数"] ``` **Diagram sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L56-L70) **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L56-L70) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L37-L38) ## 分布式追踪上下文传播 -为了实现跨服务的分布式追踪,`InitTracer()` 函数通过 `otel.SetTextMapPropagator()` 配置了全局的文本映射传播器(TextMapPropagator)。它使用 `propagation.NewCompositeTextMapPropagator` 组合了两种 W3C 标准: +为了实现跨服务的分布式追踪,`InitTracer()` 函数通过 `otel.SetTextMapPropagator()` 配置了全局的文本映射传播器(TextMapPropagator)。它使用 +`propagation.NewCompositeTextMapPropagator` 组合了两种 W3C 标准: -* **W3C Trace Context (`propagation.TraceContext{}`)**:负责在 HTTP 请求头(如 `traceparent` 和 `tracestate`)中传递追踪的上下文信息(Trace ID, Span ID 等),确保调用链路的连续性。 -* **W3C Baggage (`propagation.Baggage{}`)**:允许在请求中携带用户自定义的键值对数据(如用户ID、租户ID),这些数据会随着调用链路在所有服务间传递,为业务逻辑提供上下文。 +* **W3C Trace Context (`propagation.TraceContext{}`)**:负责在 HTTP 请求头(如 `traceparent` 和 `tracestate` + )中传递追踪的上下文信息(Trace ID, Span ID 等),确保调用链路的连续性。 +* **W3C Baggage (`propagation.Baggage{}`)**:允许在请求中携带用户自定义的键值对数据(如用户ID、租户ID),这些数据会随着调用链路在所有服务间传递,为业务逻辑提供上下文。 此配置确保了 `kami_gateway` 发起或接收的任何请求都能正确地传播和接收分布式追踪上下文。 **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L198-L203) ## 追踪资源的优雅关闭 -在 `main.go` 文件中,`InitTracer()` 函数被调用,并通过 `defer` 语句注册了其返回的关闭函数。`InitTracer()` 函数返回了三个 `Shutdown` 函数,分别用于优雅地关闭追踪、指标和日志的导出器。 +在 `main.go` 文件中,`InitTracer()` 函数被调用,并通过 `defer` 语句注册了其返回的关闭函数。`InitTracer()` 函数返回了三个 +`Shutdown` 函数,分别用于优雅地关闭追踪、指标和日志的导出器。 ```go cleanup1, cleanup2, cleanup3 := otelTrace.InitTracer() @@ -96,13 +109,15 @@ defer func() { ``` 当应用程序接收到终止信号(如 SIGTERM)并开始退出时,`defer` 语句会执行。此时,`Shutdown` 函数会被调用,它们会: -1. 将导出器缓冲区中所有待处理的追踪、指标和日志数据强制刷新(flush)到后端收集器。 -2. 等待数据发送完成或达到超时时间。 -3. 释放相关资源。 + +1. 将导出器缓冲区中所有待处理的追踪、指标和日志数据强制刷新(flush)到后端收集器。 +2. 等待数据发送完成或达到超时时间。 +3. 释放相关资源。 这个过程确保了在服务关闭前,所有重要的可观测性数据都不会丢失,实现了资源的优雅关闭。 **Section sources** + - [main.go](file://main.go#L25-L35) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L205) @@ -110,8 +125,10 @@ defer func() { 基于 `kami_gateway` 的实现,以下是一些生产环境的配置调整建议: -1. **安全连接**:在生产环境中,应优先使用 `otlptracegrpc.WithTLSCredentials()` 替代 `WithInsecure()`,通过 TLS 加密保障数据传输安全。 -2. **动态采样**:当前代码中使用了固定的采样率(`DefaultSamplingRatio`)。在高流量场景下,可以考虑实现更复杂的采样策略,如基于请求速率、错误率或特定业务逻辑的动态采样,以平衡观测需求和系统开销。 -3. **收集器地址**:`collectorURL` 在 `consts.go` 中硬编码。建议将其移至配置文件或环境变量中,以提高部署的灵活性。 -4. **监控与告警**:代码中启动了 `monitorExporterHealth()` goroutine 来监控导出器健康状态。应确保此监控机制有效,并与告警系统集成,以便在数据导出失败时及时通知运维人员。 -5. **资源限制**:根据实际的服务器资源和流量情况,调整 `MaxQueueSize` 和 `MaxExportBatchSize` 等参数,避免因缓冲区过大导致内存溢出,或因批量过小影响性能。 \ No newline at end of file +1. **安全连接**:在生产环境中,应优先使用 `otlptracegrpc.WithTLSCredentials()` 替代 `WithInsecure()`,通过 TLS 加密保障数据传输安全。 +2. **动态采样**:当前代码中使用了固定的采样率(`DefaultSamplingRatio` + )。在高流量场景下,可以考虑实现更复杂的采样策略,如基于请求速率、错误率或特定业务逻辑的动态采样,以平衡观测需求和系统开销。 +3. **收集器地址**:`collectorURL` 在 `consts.go` 中硬编码。建议将其移至配置文件或环境变量中,以提高部署的灵活性。 +4. **监控与告警**:代码中启动了 `monitorExporterHealth()` goroutine 来监控导出器健康状态。应确保此监控机制有效,并与告警系统集成,以便在数据导出失败时及时通知运维人员。 +5. **资源限制**:根据实际的服务器资源和流量情况,调整 `MaxQueueSize` 和 `MaxExportBatchSize` + 等参数,避免因缓冲区过大导致内存溢出,或因批量过小影响性能。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/资源标识与上下文配置.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/资源标识与上下文配置.md index 3eae6d8..3ca1415 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/资源标识与上下文配置.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/资源标识与上下文配置.md @@ -9,6 +9,7 @@ ## 目录 + 1. [资源对象构建](#资源对象构建) 2. [关键属性配置](#关键属性配置) 3. [上下文共享机制](#上下文共享机制) @@ -16,22 +17,31 @@ ## 资源对象构建 -在 `kami_gateway` 项目中,OpenTelemetry 的资源(Resource)对象是通过 `resource.New` 函数构建的,该过程是整个可观测性系统的基础。资源对象的创建发生在 `InitTracer` 函数内部,作为初始化追踪系统的一部分。此对象封装了服务的静态元数据,为后续的追踪、指标和日志数据提供了统一的上下文标识。 +在 `kami_gateway` 项目中,OpenTelemetry 的资源(Resource)对象是通过 `resource.New` 函数构建的,该过程是整个可观测性系统的基础。资源对象的创建发生在 +`InitTracer` 函数内部,作为初始化追踪系统的一部分。此对象封装了服务的静态元数据,为后续的追踪、指标和日志数据提供了统一的上下文标识。 -`resource.New` 函数接收一个上下文和一系列配置选项,其中核心是 `resource.WithAttributes`,它允许开发者定义一组键值对属性。这些属性在分布式系统中至关重要,它们使得来自不同服务的遥测数据能够被正确地关联、聚合和过滤。资源对象的构建是整个 `InitTracer` 流程中的关键步骤,它确保了所有后续生成的追踪、指标和日志都携带一致的元数据。 +`resource.New` 函数接收一个上下文和一系列配置选项,其中核心是 `resource.WithAttributes` +,它允许开发者定义一组键值对属性。这些属性在分布式系统中至关重要,它们使得来自不同服务的遥测数据能够被正确地关联、聚合和过滤。资源对象的构建是整个 +`InitTracer` 流程中的关键步骤,它确保了所有后续生成的追踪、指标和日志都携带一致的元数据。 **Section sources** + - [init.go](file://internal/otelTrace/init.go#L47-L55) ## 关键属性配置 资源对象通过 `attribute.String` 函数设置了三个核心属性,这些属性构成了服务的身份标识。 -`library.language` 属性被硬编码为 `"go"`,明确标识了该服务是使用 Go 语言编写的。这一信息对于运维团队和监控系统至关重要,因为它允许按编程语言对服务进行分类和分析,例如,可以快速筛选出所有 Go 语言服务的性能指标或错误日志。 +`library.language` 属性被硬编码为 `"go"`,明确标识了该服务是使用 Go +语言编写的。这一信息对于运维团队和监控系统至关重要,因为它允许按编程语言对服务进行分类和分析,例如,可以快速筛选出所有 Go +语言服务的性能指标或错误日志。 -`service.name` 属性的值来源于 `consts.go` 文件中定义的 `serviceName` 变量。该变量的值是字符串 `"网关服务——"` 与环境变量 `serverName` 的拼接结果。这种动态命名方式确保了即使在同一个代码库下部署多个实例(如不同的网关实例),每个实例也能拥有一个唯一且可识别的服务名称,便于在服务发现和监控中进行区分。 +`service.name` 属性的值来源于 `consts.go` 文件中定义的 `serviceName` 变量。该变量的值是字符串 `"网关服务——"` 与环境变量 +`serverName` 的拼接结果。这种动态命名方式确保了即使在同一个代码库下部署多个实例(如不同的网关实例),每个实例也能拥有一个唯一且可识别的服务名称,便于在服务发现和监控中进行区分。 -`deployment.environment` 属性的值通过 `env.Get("ENVIRONMENT", "production")` 从环境变量 `ENVIRONMENT` 中读取。如果该环境变量未设置,则默认值为 `"production"`。这一设计实践遵循了十二要素应用(12-Factor App)的原则,使得同一份代码可以在开发、测试、预发布和生产等不同环境中运行,而无需修改代码。监控系统可以利用此属性对不同环境的数据进行隔离分析,例如,可以对比生产环境和预发布环境的性能差异。 +`deployment.environment` 属性的值通过 `env.Get("ENVIRONMENT", "production")` 从环境变量 `ENVIRONMENT` +中读取。如果该环境变量未设置,则默认值为 `"production"`。这一设计实践遵循了十二要素应用(12-Factor +App)的原则,使得同一份代码可以在开发、测试、预发布和生产等不同环境中运行,而无需修改代码。监控系统可以利用此属性对不同环境的数据进行隔离分析,例如,可以对比生产环境和预发布环境的性能差异。 ```mermaid flowchart TD @@ -49,22 +59,30 @@ UseDefault --> End ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L49-L51) - [consts.go](file://internal/otelTrace/consts.go#L47) **Section sources** + - [init.go](file://internal/otelTrace/init.go#L49-L51) - [consts.go](file://internal/otelTrace/consts.go#L47) ## 上下文共享机制 -资源对象在 `kami_gateway` 中扮演着“上下文锚点”的角色,它被 `TracerProvider`、`MeterProvider` 和 `LoggerProvider` 共享,从而实现了追踪、指标和日志三者之间的上下文一致性。 +资源对象在 `kami_gateway` 中扮演着“上下文锚点”的角色,它被 `TracerProvider`、`MeterProvider` 和 `LoggerProvider` +共享,从而实现了追踪、指标和日志三者之间的上下文一致性。 -`TracerProvider` 在创建时,通过 `sdktrace.WithResource(resources)` 将资源对象注入。这意味着该服务生成的所有追踪(Trace)和跨度(Span)都会自动携带 `library.language`、`service.name` 和 `deployment.environment` 这些标签。这使得在分布式追踪系统中,可以轻松地根据服务名称或部署环境来过滤和聚合链路。 +`TracerProvider` 在创建时,通过 `sdktrace.WithResource(resources)` 将资源对象注入。这意味着该服务生成的所有追踪(Trace)和跨度(Span)都会自动携带 +`library.language`、`service.name` 和 `deployment.environment` 这些标签。这使得在分布式追踪系统中,可以轻松地根据服务名称或部署环境来过滤和聚合链路。 -`MeterProvider` 同样通过 `sdkMetric.WithResource(resources)` 接收资源对象。这确保了该服务上报的所有指标(如请求延迟、错误率)都带有相同的服务标识。监控系统可以基于这些标签进行多维度的数据切片和聚合,例如,计算生产环境中所有网关服务的平均响应时间。 +`MeterProvider` 同样通过 `sdkMetric.WithResource(resources)` +接收资源对象。这确保了该服务上报的所有指标(如请求延迟、错误率)都带有相同的服务标识。监控系统可以基于这些标签进行多维度的数据切片和聚合,例如,计算生产环境中所有网关服务的平均响应时间。 -`LoggerProvider` 通过 `sdklog.WithResource(resources)` 将资源对象与日志系统绑定。这使得通过 OpenTelemetry 导出的日志条目也包含了服务的元数据。更重要的是,项目中定义了一个 `CustomLogger` 结构体,它封装了 `zap.Logger`,并提供了一个 `WithContext` 方法。该方法能够从传入的 `context.Context` 中提取追踪上下文(如 Trace ID 和 Span ID),并将其作为字段注入到日志中。这实现了日志与追踪的深度关联,运维人员可以通过一个 Trace ID 在日志系统中直接搜索到与该次请求相关的所有日志。 +`LoggerProvider` 通过 `sdklog.WithResource(resources)` 将资源对象与日志系统绑定。这使得通过 OpenTelemetry +导出的日志条目也包含了服务的元数据。更重要的是,项目中定义了一个 `CustomLogger` 结构体,它封装了 `zap.Logger`,并提供了一个 +`WithContext` 方法。该方法能够从传入的 `context.Context` 中提取追踪上下文(如 Trace ID 和 Span +ID),并将其作为字段注入到日志中。这实现了日志与追踪的深度关联,运维人员可以通过一个 Trace ID 在日志系统中直接搜索到与该次请求相关的所有日志。 ```mermaid graph TD @@ -86,6 +104,7 @@ classDef provider fill:#f3e5f5,stroke:#8e24aa,stroke-width:2px; ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L58-L62) - [init.go](file://internal/otelTrace/init.go#L84-L88) - [init.go](file://internal/otelTrace/init.go#L112-L116) @@ -93,6 +112,7 @@ classDef provider fill:#f3e5f5,stroke:#8e24aa,stroke-width:2px; - [logs.go](file://internal/otelTrace/logs.go#L9-L11) **Section sources** + - [init.go](file://internal/otelTrace/init.go#L58-L62) - [init.go](file://internal/otelTrace/init.go#L84-L88) - [init.go](file://internal/otelTrace/init.go#L112-L116) @@ -101,9 +121,13 @@ classDef provider fill:#f3e5f5,stroke:#8e24aa,stroke-width:2px; ## 初始化流程 -资源对象的构建和共享是 `InitTracer` 函数执行流程中的一个环节。该函数的调用发生在 `main.go` 文件的 `main` 函数中,是服务启动过程的关键步骤。`InitTracer` 不仅负责创建资源对象,还负责配置追踪、指标和日志的导出器(Exporter),并将它们与各自的 Provider 绑定。 +资源对象的构建和共享是 `InitTracer` 函数执行流程中的一个环节。该函数的调用发生在 `main.go` 文件的 `main` +函数中,是服务启动过程的关键步骤。`InitTracer` 不仅负责创建资源对象,还负责配置追踪、指标和日志的导出器(Exporter),并将它们与各自的 +Provider 绑定。 -在 `main` 函数中,`otelTrace.InitTracer()` 被调用,其返回的三个 `Shutdown` 函数通过 `defer` 语句注册,确保在服务退出时能够优雅地关闭所有可观测性组件,避免数据丢失。`InitTracer` 函数内部的执行顺序是:首先创建资源对象,然后基于该资源对象初始化 `TracerProvider`、`MeterProvider` 和 `LoggerProvider`,最后将这些 Provider 设置为全局单例。 +在 `main` 函数中,`otelTrace.InitTracer()` 被调用,其返回的三个 `Shutdown` 函数通过 `defer` +语句注册,确保在服务退出时能够优雅地关闭所有可观测性组件,避免数据丢失。`InitTracer` 函数内部的执行顺序是:首先创建资源对象,然后基于该资源对象初始化 +`TracerProvider`、`MeterProvider` 和 `LoggerProvider`,最后将这些 Provider 设置为全局单例。 这种设计模式确保了整个应用生命周期内,所有组件使用的都是同一个、配置一致的可观测性基础设施。通过在应用启动时集中配置,避免了在代码各处分散配置所带来的不一致性和维护困难。 @@ -127,9 +151,11 @@ Main->>Main : defer 执行 cleanup ``` **Diagram sources** + - [main.go](file://main.go#L23-L26) - [init.go](file://internal/otelTrace/init.go#L29-L205) **Section sources** + - [main.go](file://main.go#L23-L26) - [init.go](file://internal/otelTrace/init.go#L29-L205) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/追踪导出器配置.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/追踪导出器配置.md index a335e2c..4629519 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/追踪导出器配置.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/追踪导出器配置.md @@ -11,6 +11,7 @@ ## 目录 + 1. [项目结构](#项目结构) 2. [核心组件](#核心组件) 3. [追踪导出器配置机制](#追踪导出器配置机制) @@ -50,27 +51,33 @@ otelTrace --> logs[logs.go] ``` **Diagram sources** + - [main.go](file://main.go#L1-L58) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L56) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L1-L257) **Section sources** + - [main.go](file://main.go#L1-L58) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L56) ## 核心组件 -本项目的核心组件包括OpenTelemetry追踪系统、配置管理、服务路由和代理池等模块。其中,OpenTelemetry追踪系统通过`internal/otelTrace`包实现,负责分布式追踪、指标收集和日志导出功能。该系统与后端收集器通过gRPC协议通信,实现了生产级的可观测性解决方案。 +本项目的核心组件包括OpenTelemetry追踪系统、配置管理、服务路由和代理池等模块。其中,OpenTelemetry追踪系统通过 +`internal/otelTrace`包实现,负责分布式追踪、指标收集和日志导出功能。该系统与后端收集器通过gRPC协议通信,实现了生产级的可观测性解决方案。 **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L1-L257) - [internal/config/config.go](file://internal/config/config.go) ## 追踪导出器配置机制 -kami_gateway中的OpenTelemetry追踪导出器配置机制通过`InitTracer`函数实现,该函数在应用启动时初始化追踪、指标和日志的导出器。配置机制采用生产环境优化策略,包括动态采样率、批量传输优化和资源标识配置。 +kami_gateway中的OpenTelemetry追踪导出器配置机制通过`InitTracer` +函数实现,该函数在应用启动时初始化追踪、指标和日志的导出器。配置机制采用生产环境优化策略,包括动态采样率、批量传输优化和资源标识配置。 -导出器配置的核心是`otlptracegrpc.NewClient`,它创建了一个gRPC客户端用于与后端收集器通信。同时,系统还配置了指标导出器和日志导出器,形成完整的可观测性解决方案。资源标识配置包含了服务名称、部署环境等关键属性,便于在分布式系统中识别和关联追踪数据。 +导出器配置的核心是`otlptracegrpc.NewClient` +,它创建了一个gRPC客户端用于与后端收集器通信。同时,系统还配置了指标导出器和日志导出器,形成完整的可观测性解决方案。资源标识配置包含了服务名称、部署环境等关键属性,便于在分布式系统中识别和关联追踪数据。 ```mermaid classDiagram @@ -103,17 +110,21 @@ InitTracer --> global : "设置LoggerProvider" ``` **Diagram sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L29-L205) **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L29-L205) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L56) ## gRPC通信配置 -追踪导出器通过gRPC协议与后端收集器通信,配置中包含了多个关键参数。`WithInsecure`模式用于建立非加密连接,适用于内部网络环境,降低了TLS握手的性能开销。`WithEndpoint`指定了收集器的端点地址,当前配置为`38.38.251.113:31547`。 +追踪导出器通过gRPC协议与后端收集器通信,配置中包含了多个关键参数。`WithInsecure`模式用于建立非加密连接,适用于内部网络环境,降低了TLS握手的性能开销。 +`WithEndpoint`指定了收集器的端点地址,当前配置为`38.38.251.113:31547`。 -gRPC通信配置还包含了批量传输队列的优化设置,如`WithBatchTimeout`设置为5秒的批量发送间隔,`WithMaxExportBatchSize`限制单次导出批量为512条,`WithMaxQueueSize`设置最大队列大小为2048条。这些配置平衡了实时性和性能,防止内存溢出。 +gRPC通信配置还包含了批量传输队列的优化设置,如`WithBatchTimeout`设置为5秒的批量发送间隔,`WithMaxExportBatchSize` +限制单次导出批量为512条,`WithMaxQueueSize`设置最大队列大小为2048条。这些配置平衡了实时性和性能,防止内存溢出。 ```mermaid sequenceDiagram @@ -136,18 +147,23 @@ end ``` **Diagram sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L33-L75) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L56) **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L33-L75) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L56) ## 超时与重试机制 -系统配置了5秒的默认超时(`DefaultTimeout`),这对系统稳定性至关重要。超时设置平衡了响应性和稳定性,避免因网络延迟导致的长时间阻塞。同时,系统实现了生产级的重试机制,通过`RetryConfig`进行调优。 +系统配置了5秒的默认超时(`DefaultTimeout`),这对系统稳定性至关重要。超时设置平衡了响应性和稳定性,避免因网络延迟导致的长时间阻塞。同时,系统实现了生产级的重试机制,通过 +`RetryConfig`进行调优。 -重试机制的生产级调优策略包括:1秒的初始重试间隔(`InitialRetryInterval`),允许快速恢复;10秒的最大重试间隔(`MaxRetryInterval`),避免频繁重试造成网络拥塞;30秒的最大重试总时间(`MaxRetryElapsedTime`),防止长时间阻塞。这些参数共同构成了一个指数退避重试策略,有效应对网络抖动。 +重试机制的生产级调优策略包括:1秒的初始重试间隔(`InitialRetryInterval`),允许快速恢复;10秒的最大重试间隔( +`MaxRetryInterval`),避免频繁重试造成网络拥塞;30秒的最大重试总时间(`MaxRetryElapsedTime` +),防止长时间阻塞。这些参数共同构成了一个指数退避重试策略,有效应对网络抖动。 ```mermaid flowchart TD @@ -170,29 +186,35 @@ End --> Cleanup["清理资源"] ``` **Diagram sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L38-L75) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L56) **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L38-L75) - [internal/otelTrace/consts.go](file://internal/otelTrace/consts.go#L1-L56) ## 数据压缩与网络优化 -系统通过`WithCompressor("gzip")`配置启用gzip压缩,显著降低网络传输开销。这一配置应用于追踪、指标和日志三种数据类型的导出器,实现了全面的网络优化。gzip压缩在高负载场景下尤为重要,可以大幅减少带宽消耗和传输延迟。 +系统通过`WithCompressor("gzip")` +配置启用gzip压缩,显著降低网络传输开销。这一配置应用于追踪、指标和日志三种数据类型的导出器,实现了全面的网络优化。gzip压缩在高负载场景下尤为重要,可以大幅减少带宽消耗和传输延迟。 除了数据压缩,系统还实施了多项网络优化策略。批量传输机制减少了网络请求次数,5秒的批量发送间隔平衡了实时性和性能。最大导出批量(512条)和最大队列大小(2048条)的设置防止了单次传输过大导致的网络拥塞和内存溢出问题。 **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L68-L75) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L104-L111) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L135-L140) ## 优雅关闭机制 -`traceExporter.Shutdown`函数在`main.go`中通过defer调用实现优雅关闭行为。该机制确保在应用终止时,所有待处理的追踪数据都能被完整导出,避免数据丢失。优雅关闭是生产环境的关键特性,保证了可观测性数据的完整性。 +`traceExporter.Shutdown`函数在`main.go` +中通过defer调用实现优雅关闭行为。该机制确保在应用终止时,所有待处理的追踪数据都能被完整导出,避免数据丢失。优雅关闭是生产环境的关键特性,保证了可观测性数据的完整性。 -在`main.go`中,`InitTracer`函数返回三个清理函数,分别用于追踪、指标和日志导出器的关闭。defer语句确保这些清理函数在main函数退出时执行,即使发生panic也能保证资源的正确释放。这种设计模式提高了系统的可靠性和稳定性。 +在`main.go`中,`InitTracer` +函数返回三个清理函数,分别用于追踪、指标和日志导出器的关闭。defer语句确保这些清理函数在main函数退出时执行,即使发生panic也能保证资源的正确释放。这种设计模式提高了系统的可靠性和稳定性。 ```mermaid sequenceDiagram @@ -212,18 +234,22 @@ Shutdown-->>Main : 完成优雅关闭 ``` **Diagram sources** + - [main.go](file://main.go#L30-L38) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L204-L205) **Section sources** + - [main.go](file://main.go#L30-L38) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L204-L205) ## 熔断与健康监控 -系统实现了熔断器模式和健康监控机制,增强了追踪系统的可靠性。`CircuitBreaker`结构体实现了简单的熔断器,当连续失败达到阈值(5次)时,熔断器开启,避免对后端收集器造成持续压力。30秒的重置超时允许系统在故障恢复后自动恢复正常。 +系统实现了熔断器模式和健康监控机制,增强了追踪系统的可靠性。`CircuitBreaker` +结构体实现了简单的熔断器,当连续失败达到阈值(5次)时,熔断器开启,避免对后端收集器造成持续压力。30秒的重置超时允许系统在故障恢复后自动恢复正常。 -`monitorExporterHealth`函数作为后台goroutine运行,每30秒检查一次导出器的健康状态。它监控错误率,当失败次数超过阈值时发出警告。同时,系统实现了动态采样率调整机制,在检测到高负载时自动降低采样率(从10%降至5%),保护系统稳定性。 +`monitorExporterHealth` +函数作为后台goroutine运行,每30秒检查一次导出器的健康状态。它监控错误率,当失败次数超过阈值时发出警告。同时,系统实现了动态采样率调整机制,在检测到高负载时自动降低采样率(从10%降至5%),保护系统稳定性。 ```mermaid stateDiagram-v2 @@ -248,9 +274,11 @@ end note ``` **Diagram sources** + - [internal/otelTrace/circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L1-L50) - [internal/otelTrace/utils.go](file://internal/otelTrace/utils.go#L16-L46) **Section sources** + - [internal/otelTrace/circuit_breaker.go](file://internal/otelTrace/circuit_breaker.go#L1-L50) - [internal/otelTrace/utils.go](file://internal/otelTrace/utils.go#L16-L46) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/采样策略与批量处理.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/采样策略与批量处理.md index ddc0c76..c8c4d14 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/采样策略与批量处理.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/初始化与资源配置/采样策略与批量处理.md @@ -10,6 +10,7 @@ ## 目录 + 1. [引言](#引言) 2. [采样策略详解](#采样策略详解) 3. [批量处理机制](#批量处理机制) @@ -18,15 +19,20 @@ 6. [结论](#结论) ## 引言 -本文档详细解析 kami_gateway 项目中 OpenTelemetry 的采样策略与批量处理机制。通过分析 `traceIDRatioBased` 采样器如何基于比率控制生成的追踪数据量,以及 `sdktrace.NewBatchSpanProcessor` 的配置参数,深入探讨这些机制如何在监控精度与系统性能开销之间取得平衡。文档结合生产环境需求,分析这些参数对高并发支付场景下的性能影响,并提供相应的调优建议。 + +本文档详细解析 kami_gateway 项目中 OpenTelemetry 的采样策略与批量处理机制。通过分析 `traceIDRatioBased` +采样器如何基于比率控制生成的追踪数据量,以及 `sdktrace.NewBatchSpanProcessor` +的配置参数,深入探讨这些机制如何在监控精度与系统性能开销之间取得平衡。文档结合生产环境需求,分析这些参数对高并发支付场景下的性能影响,并提供相应的调优建议。 **Section sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [simple.go](file://internal/otelTrace/simple.go#L80-L93) ## 采样策略详解 ### traceIDRatioBased 采样器 + `traceIDRatioBased` 采样器是 kami_gateway 项目中用于控制追踪数据生成量的核心机制。该采样器基于给定的比率对追踪进行采样,确保在高负载场景下既能保持足够的监控精度,又不会对系统性能造成过大开销。 ```mermaid @@ -44,23 +50,32 @@ Record --> End ``` **Diagram sources** + - [simple.go](file://internal/otelTrace/simple.go#L80-L93) #### 采样逻辑实现 -`traceIDRatioBased` 函数接收一个浮点数 `fraction` 作为采样比率参数。当比率大于等于1时,返回 `sdkTrace.AlwaysSample()`,表示始终采样;当比率小于等于0时,将其设置为0,表示不采样。对于介于0和1之间的比率,函数创建并返回一个 `traceIDRatioSampler` 结构体实例,该实例包含 `traceIDUpperBound` 和描述信息。 -`traceIDUpperBound` 是通过将采样比率乘以 `1 << 63` 计算得出的,这确保了采样决策的均匀分布。在 `ShouldSample` 方法中,系统通过比较生成的 TraceID 与 `traceIDUpperBound` 来决定是否采样该 Span。 +`traceIDRatioBased` 函数接收一个浮点数 `fraction` 作为采样比率参数。当比率大于等于1时,返回 `sdkTrace.AlwaysSample()` +,表示始终采样;当比率小于等于0时,将其设置为0,表示不采样。对于介于0和1之间的比率,函数创建并返回一个 `traceIDRatioSampler` +结构体实例,该实例包含 `traceIDUpperBound` 和描述信息。 + +`traceIDUpperBound` 是通过将采样比率乘以 `1 << 63` 计算得出的,这确保了采样决策的均匀分布。在 `ShouldSample` 方法中,系统通过比较生成的 +TraceID 与 `traceIDUpperBound` 来决定是否采样该 Span。 #### 强制采样机制 -除了基于比率的采样外,系统还实现了强制采样机制。对于特定的追踪名称(如 "PayNotify"、"HandleSendCardTask")或包含错误属性的 Span,系统会强制进行采样,确保关键业务流程和错误情况能够被完整记录。 + +除了基于比率的采样外,系统还实现了强制采样机制。对于特定的追踪名称(如 "PayNotify"、"HandleSendCardTask")或包含错误属性的 +Span,系统会强制进行采样,确保关键业务流程和错误情况能够被完整记录。 **Section sources** + - [simple.go](file://internal/otelTrace/simple.go#L1-L94) - [consts.go](file://internal/otelTrace/consts.go#L30-L33) ## 批量处理机制 ### 批量处理器配置 + kami_gateway 使用 `sdktrace.NewBatchSpanProcessor` 来优化追踪数据的导出过程。该处理器通过批量处理 Span,显著减少了网络传输次数和系统开销。 ```mermaid @@ -86,9 +101,11 @@ BatchSpanProcessor --> SpanExporter : "使用" ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L60-L75) #### 核心配置参数 + 批量处理器的配置参数经过精心设计,以优化内存使用与吞吐量: - **BatchTimeout (5秒)**:控制批量发送的频率。每5秒,处理器会将队列中的 Span 批量导出,平衡了实时性与性能。 @@ -97,12 +114,14 @@ BatchSpanProcessor --> SpanExporter : "使用" - **ExportTimeout (5秒)**:防止导出操作阻塞。如果导出操作在5秒内未完成,将被中断,避免影响主业务流程。 **Section sources** + - [init.go](file://internal/otelTrace/init.go#L60-L75) - [consts.go](file://internal/otelTrace/consts.go#L20-L25) ## 生产环境性能分析 ### 系统性能影响 + 在高并发支付场景下,OpenTelemetry 的采样与批量处理机制对系统性能有着重要影响。合理的配置能够显著降低系统开销,同时保持足够的监控精度。 ```mermaid @@ -126,10 +145,12 @@ end ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [consts.go](file://internal/otelTrace/consts.go#L15-L35) #### 动态采样率调整 + 系统实现了动态采样率调整机制,通过 `monitorExporterHealth` 函数定期检查导出器的健康状态。当导出失败次数超过阈值时,系统会自动降低采样率,从默认的10%降至5%,以保护系统稳定性。 ```mermaid @@ -152,16 +173,19 @@ Monitor->>Monitor : 重置失败计数器 ``` **Diagram sources** + - [utils.go](file://internal/otelTrace/utils.go#L16-L46) - [consts.go](file://internal/otelTrace/consts.go#L33-L34) **Section sources** + - [utils.go](file://internal/otelTrace/utils.go#L16-L46) - [consts.go](file://internal/otelTrace/consts.go#L33-L34) ## 高并发支付场景调优建议 ### 参数调优策略 + 针对高并发支付场景,建议根据实际负载情况对 OpenTelemetry 的配置参数进行调优: - **采样率**:在正常负载下保持10%的采样率,以确保足够的监控精度。在高负载或系统资源紧张时,可动态降低至5%,以保护系统稳定性。 @@ -170,11 +194,16 @@ Monitor->>Monitor : 重置失败计数器 - **队列大小**:2048条的最大队列大小能够有效应对突发流量。在内存充足的系统中,可适当增加至4096条,以提供更大的缓冲空间。 ### 监控与告警 + 建议建立完善的监控与告警机制,实时监控 OpenTelemetry 导出器的健康状态。当导出失败率持续升高时,应及时调整采样率或检查后端服务的稳定性。 **Section sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [utils.go](file://internal/otelTrace/utils.go#L16-L46) ## 结论 -kami_gateway 项目中的 OpenTelemetry 采样与批量处理机制经过精心设计,能够在高并发支付场景下有效平衡监控精度与系统性能开销。通过 `traceIDRatioBased` 采样器和 `sdktrace.NewBatchSpanProcessor` 的合理配置,系统能够在保证关键业务流程监控的同时,最大限度地减少对主业务流程的影响。建议根据实际生产环境的需求,灵活调整相关参数,以达到最佳的性能与监控效果。 \ No newline at end of file + +kami_gateway 项目中的 OpenTelemetry 采样与批量处理机制经过精心设计,能够在高并发支付场景下有效平衡监控精度与系统性能开销。通过 +`traceIDRatioBased` 采样器和 `sdktrace.NewBatchSpanProcessor` +的合理配置,系统能够在保证关键业务流程监控的同时,最大限度地减少对主业务流程的影响。建议根据实际生产环境的需求,灵活调整相关参数,以达到最佳的性能与监控效果。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/日志与追踪上下文关联.md b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/日志与追踪上下文关联.md index 8d17a72..3ebecef 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/日志与追踪上下文关联.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/OpenTelemetry 分布式追踪/日志与追踪上下文关联.md @@ -8,6 +8,7 @@ ## 目录 + 1. [简介](#简介) 2. [CustomLogger 结构体设计](#customlogger-结构体设计) 3. [日志与 OTLP 集成机制](#日志与-otlp-集成机制) @@ -16,13 +17,18 @@ 6. [总结](#总结) ## 简介 -本文档详细阐述 kami_gateway 项目中日志系统与分布式追踪系统的深度集成方案。重点分析 `CustomLogger` 结构体的设计原理,特别是 `WithContext()` 方法如何从 `context.Context` 中提取有效的 Span,并将上下文信息注入日志字段。同时说明在上下文无效或缺失时的降级处理逻辑,以及如何通过 OTLP 协议将日志导出至集中式观测平台,同时保留本地控制台输出用于调试。该集成机制有效实现了日志与追踪上下文的关联,极大提升了分布式系统的问题排查效率。 + +本文档详细阐述 kami_gateway 项目中日志系统与分布式追踪系统的深度集成方案。重点分析 `CustomLogger` 结构体的设计原理,特别是 +`WithContext()` 方法如何从 `context.Context` 中提取有效的 Span,并将上下文信息注入日志字段。同时说明在上下文无效或缺失时的降级处理逻辑,以及如何通过 +OTLP 协议将日志导出至集中式观测平台,同时保留本地控制台输出用于调试。该集成机制有效实现了日志与追踪上下文的关联,极大提升了分布式系统的问题排查效率。 ## CustomLogger 结构体设计 -`CustomLogger` 是 kami_gateway 中用于封装日志功能的核心结构体,其设计目标是实现日志与 OpenTelemetry 分布式追踪上下文的无缝集成。该结构体通过 `WithContext()` 方法实现上下文感知的日志记录能力。 +`CustomLogger` 是 kami_gateway 中用于封装日志功能的核心结构体,其设计目标是实现日志与 OpenTelemetry 分布式追踪上下文的无缝集成。该结构体通过 +`WithContext()` 方法实现上下文感知的日志记录能力。 `WithContext()` 方法的实现逻辑如下: + - 当传入的 `context.Context` 为 `nil` 时,直接返回原始日志记录器,避免空指针异常。 - 使用 `trace.SpanFromContext(ctx)` 从上下文中提取当前活动的 Span。 - 检查 Span 上下文的有效性(`IsValid()`),若无效则返回原始日志记录器或 `zap.NewNop()`(当日志器为空时)。 @@ -30,7 +36,8 @@ 这种设计确保了在任何执行路径下日志系统都能稳定运行,即使在无追踪上下文的场景中也不会中断日志输出。 -**节来源** +**节来源** + - [logs.go](file://internal/otelTrace/logs.go#L9-L28) ## 日志与 OTLP 集成机制 @@ -38,23 +45,30 @@ 在 `init.go` 文件中,通过 `otelzap.NewCore` 实现了日志到 OTLP 的导出集成。具体实现方式如下: 日志核心(core)通过 `zapcore.NewTee` 组合了两个输出目标: -1. **OTLP 日志导出器**:使用 `otelzap.NewCore(serviceName, otelzap.WithLoggerProvider(loggerProvider))` 创建,将日志发送至配置的 OTLP 收集器(collectorURL)。 + +1. **OTLP 日志导出器**:使用 `otelzap.NewCore(serviceName, otelzap.WithLoggerProvider(loggerProvider))` 创建,将日志发送至配置的 + OTLP 收集器(collectorURL)。 2. **控制台输出**:使用 `zapcore.NewConsoleEncoder` 配合 `os.Stdout` 实现,保留本地调试输出能力。 -该机制确保了生产环境中日志既能上报至集中式观测平台,又能在开发或调试阶段提供实时控制台输出。同时,日志导出器配置了超时、重试、gzip 压缩等生产级优化参数,保障了高负载场景下的稳定性。 +该机制确保了生产环境中日志既能上报至集中式观测平台,又能在开发或调试阶段提供实时控制台输出。同时,日志导出器配置了超时、重试、gzip +压缩等生产级优化参数,保障了高负载场景下的稳定性。 + +**节来源** -**节来源** - [init.go](file://internal/otelTrace/init.go#L130-L180) ## 日志与 Trace ID 关联分析 -kami_gateway 通过将 `context.Context` 注入日志字段的方式,实现了日志与 Trace ID 的自动关联。当请求经过启用了 OpenTelemetry 的中间件时,上下文会携带当前 Span 信息。通过 `WithContext()` 方法,该上下文被附加到日志记录器中,使得所有后续日志条目都隐式包含追踪上下文。 +kami_gateway 通过将 `context.Context` 注入日志字段的方式,实现了日志与 Trace ID 的自动关联。当请求经过启用了 OpenTelemetry +的中间件时,上下文会携带当前 Span 信息。通过 `WithContext()` 方法,该上下文被附加到日志记录器中,使得所有后续日志条目都隐式包含追踪上下文。 -在观测平台中,可通过 Trace ID 直接检索与该请求相关的所有日志条目,形成完整的调用链视图。这种关联机制无需在业务代码中手动传递 Trace ID,降低了开发复杂度,同时保证了日志与追踪数据的一致性。 +在观测平台中,可通过 Trace ID 直接检索与该请求相关的所有日志条目,形成完整的调用链视图。这种关联机制无需在业务代码中手动传递 +Trace ID,降低了开发复杂度,同时保证了日志与追踪数据的一致性。 此外,系统还配置了 W3C Trace Context 和 Baggage 的复合传播器,确保跨服务调用时上下文信息的正确传递,支持完整的端到端分布式追踪。 -**节来源** +**节来源** + - [init.go](file://internal/otelTrace/init.go#L200-L205) - [logs.go](file://internal/otelTrace/logs.go#L20-L27) @@ -83,13 +97,19 @@ func HandleRequest(ctx context.Context, req *Request) { ``` 关键要点: + - 始终使用 `otelTrace.Logger.WithContext(ctx)` 获取日志器,而非直接使用 `zap.L()`。 - 确保传入有效的 `context.Context`,通常由 HTTP 中间件或 RPC 框架提供。 - 避免在无上下文的场景中强制传递 `nil`,`WithContext()` 方法已处理该情况。 -**节来源** +**节来源** + - [logs.go](file://internal/otelTrace/logs.go#L13-L28) - [init.go](file://internal/otelTrace/init.go#L178) ## 总结 -kami_gateway 通过 `CustomLogger` 结构体和 `WithContext()` 方法,实现了日志系统与 OpenTelemetry 分布式追踪的深度集成。该方案具备良好的健壮性,支持上下文缺失时的优雅降级,并通过 OTLP 协议实现日志的集中化管理。日志与 Trace ID 的自动关联极大提升了系统可观测性,为分布式环境下的问题排查提供了有力支持。建议在所有业务组件中统一采用 `WithContext()` 模式,确保日志上下文的一致性和完整性。 \ No newline at end of file + +kami_gateway 通过 `CustomLogger` 结构体和 `WithContext()` 方法,实现了日志系统与 OpenTelemetry +分布式追踪的深度集成。该方案具备良好的健壮性,支持上下文缺失时的优雅降级,并通过 OTLP 协议实现日志的集中化管理。日志与 Trace +ID 的自动关联极大提升了系统可观测性,为分布式环境下的问题排查提供了有力支持。建议在所有业务组件中统一采用 `WithContext()` +模式,确保日志上下文的一致性和完整性。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/技术栈与依赖.md b/.qoder/repowiki/zh/content/技术栈与依赖/技术栈与依赖.md index c8e5ae5..63b9519 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/技术栈与依赖.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/技术栈与依赖.md @@ -14,6 +14,7 @@ ## 目录 + 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) @@ -25,10 +26,18 @@ 9. [结论](#结论) ## 简介 -本文档详细阐述了 `kami_gateway` 项目的技术栈及其在项目中的具体应用。文档深入分析了 Beego v2 框架的使用,包括路由配置、控制器继承和中间件机制。同时,详细说明了 OpenTelemetry 分布式追踪系统的实现,涵盖 `otelTrace` 包中的 span 创建、日志集成和链路追踪上下文传递。文档还解释了 Redis 在缓存(`internal/cache`)和代理池管理中的双重角色,描述了 MySQL 数据库通过 Beego ORM 进行数据访问的模式,以及 RabbitMQ 在订单通知和查询消费者中的异步消息处理机制。最后,结合 `main.go` 中的初始化代码,说明了这些技术组件是如何被集成和启动的,并提供了每个技术选型的决策理由、版本兼容性要求和性能考量,以及配置最佳实践。 + +本文档详细阐述了 `kami_gateway` 项目的技术栈及其在项目中的具体应用。文档深入分析了 Beego v2 +框架的使用,包括路由配置、控制器继承和中间件机制。同时,详细说明了 OpenTelemetry 分布式追踪系统的实现,涵盖 `otelTrace` 包中的 +span 创建、日志集成和链路追踪上下文传递。文档还解释了 Redis 在缓存(`internal/cache`)和代理池管理中的双重角色,描述了 MySQL +数据库通过 Beego ORM 进行数据访问的模式,以及 RabbitMQ 在订单通知和查询消费者中的异步消息处理机制。最后,结合 `main.go` +中的初始化代码,说明了这些技术组件是如何被集成和启动的,并提供了每个技术选型的决策理由、版本兼容性要求和性能考量,以及配置最佳实践。 ## 项目结构 -项目采用分层架构,主要分为 `conf`、`deploy`、`internal` 和根目录文件。`conf` 目录存放应用配置文件 `app.conf`。`deploy` 目录包含 Docker 部署相关的 `Dockerfile` 和 `docker-compose` 文件。`internal` 目录是项目的核心,包含了所有业务逻辑和基础设施代码,主要子目录包括: + +项目采用分层架构,主要分为 `conf`、`deploy`、`internal` 和根目录文件。`conf` 目录存放应用配置文件 `app.conf`。`deploy` 目录包含 +Docker 部署相关的 `Dockerfile` 和 `docker-compose` 文件。`internal` 目录是项目的核心,包含了所有业务逻辑和基础设施代码,主要子目录包括: + - `cache`: Redis 缓存客户端封装。 - `config`: 应用配置和常量定义。 - `controllers`: Beego 控制器,处理 HTTP 请求。 @@ -80,23 +89,33 @@ deploy --> main ``` **Diagram sources** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) **Section sources** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) ## 核心组件 -本项目的核心组件围绕 Beego Web 框架构建,通过 `main.go` 文件进行初始化和集成。核心功能包括基于 Beego 的 HTTP 路由和控制器处理、通过 `otelTrace` 实现的分布式追踪、利用 Redis 实现的缓存和代理池、通过 Beego ORM 访问 MySQL 数据库,以及使用 RabbitMQ 进行异步消息处理。这些组件共同构成了一个高可用、可观测的网关服务。 + +本项目的核心组件围绕 Beego Web 框架构建,通过 `main.go` 文件进行初始化和集成。核心功能包括基于 Beego 的 HTTP 路由和控制器处理、通过 +`otelTrace` 实现的分布式追踪、利用 Redis 实现的缓存和代理池、通过 Beego ORM 访问 MySQL 数据库,以及使用 RabbitMQ +进行异步消息处理。这些组件共同构成了一个高可用、可观测的网关服务。 **Section sources** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L1-L256) ## 架构概览 -系统采用典型的微服务网关架构。外部请求首先到达 Beego Web 服务器,经过 `otelTrace` 中间件进行分布式追踪和性能监控。请求被路由到相应的控制器(如 `ScanController`),控制器调用 `service` 层进行业务逻辑处理。业务逻辑层会通过 `models` 层的 Beego ORM 与 MySQL 数据库交互,并利用 `cache` 模块中的 Redis 客户端进行缓存读写。同时,系统通过 `notify` 和 `query` 模块启动后台消费者,从 RabbitMQ 消息队列中消费订单通知和查询任务,实现异步解耦。整个系统的可观测性由 OpenTelemetry 提供,所有追踪、指标和日志数据被导出到后端收集器。 + +系统采用典型的微服务网关架构。外部请求首先到达 Beego Web 服务器,经过 `otelTrace` 中间件进行分布式追踪和性能监控。请求被路由到相应的控制器(如 +`ScanController`),控制器调用 `service` 层进行业务逻辑处理。业务逻辑层会通过 `models` 层的 Beego ORM 与 MySQL 数据库交互,并利用 +`cache` 模块中的 Redis 客户端进行缓存读写。同时,系统通过 `notify` 和 `query` 模块启动后台消费者,从 RabbitMQ +消息队列中消费订单通知和查询任务,实现异步解耦。整个系统的可观测性由 OpenTelemetry 提供,所有追踪、指标和日志数据被导出到后端收集器。 ```mermaid graph TD @@ -130,6 +149,7 @@ style Cache fill:#fcc,stroke:#333 ``` **Diagram sources** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) @@ -139,21 +159,30 @@ style Cache fill:#fcc,stroke:#333 ## 详细组件分析 ### Beego v2 框架应用分析 + Beego v2 框架是本项目的核心 Web 框架。它负责处理所有 HTTP 请求、路由分发和控制器逻辑。 #### 路由配置 -项目的路由配置位于 `internal/routers/router.go` 文件中。通过调用 `web.Router` 函数,将不同的 URL 路径映射到对应的控制器和方法。例如,`/gateway/scan` 路径被映射到 `ScanController` 的 `Scan` 方法。此外,通过 `web.InsertFilterChain` 注册了一个全局过滤器链,将 `otelTrace.Middleware` 应用于所有路径(`*`),实现了对所有请求的统一追踪。 + +项目的路由配置位于 `internal/routers/router.go` 文件中。通过调用 `web.Router` 函数,将不同的 URL 路径映射到对应的控制器和方法。例如, +`/gateway/scan` 路径被映射到 `ScanController` 的 `Scan` 方法。此外,通过 `web.InsertFilterChain` 注册了一个全局过滤器链,将 +`otelTrace.Middleware` 应用于所有路径(`*`),实现了对所有请求的统一追踪。 #### 控制器继承 -控制器通过继承 Beego 的 `web.Controller` 来获得处理 HTTP 请求的能力。`internal/controllers/base_controller.go` 定义了 `BaseGateway` 结构体,它直接嵌入了 `web.Controller`。项目中的其他控制器,如 `ScanController`,通过继承 `BaseGateway` 来复用基础功能,实现了代码的复用和分层。 + +控制器通过继承 Beego 的 `web.Controller` 来获得处理 HTTP 请求的能力。`internal/controllers/base_controller.go` 定义了 +`BaseGateway` 结构体,它直接嵌入了 `web.Controller`。项目中的其他控制器,如 `ScanController`,通过继承 `BaseGateway` +来复用基础功能,实现了代码的复用和分层。 #### 中间件使用 + `otelTrace.Middleware` 是一个关键的中间件,它被注入到请求处理链中。该中间件的主要职责是: -1. **创建追踪 Span**:为每个 HTTP 请求创建一个新的追踪 Span,记录请求的路径、方法、状态码等信息。 -2. **上下文传递**:从请求头中提取上游服务的追踪上下文(Trace Context),并将其注入到当前请求的上下文中,实现跨服务的链路追踪。 -3. **性能监控**:记录请求的处理时长,并对慢请求(超过5秒)进行告警。 -4. **错误处理**:捕获处理过程中的 panic,记录错误信息,并返回 500 错误,实现优雅降级。 -5. **熔断保护**:集成了熔断器,当追踪系统自身出现异常时,可以自动熔断,避免影响核心业务。 + +1. **创建追踪 Span**:为每个 HTTP 请求创建一个新的追踪 Span,记录请求的路径、方法、状态码等信息。 +2. **上下文传递**:从请求头中提取上游服务的追踪上下文(Trace Context),并将其注入到当前请求的上下文中,实现跨服务的链路追踪。 +3. **性能监控**:记录请求的处理时长,并对慢请求(超过5秒)进行告警。 +4. **错误处理**:捕获处理过程中的 panic,记录错误信息,并返回 500 错误,实现优雅降级。 +5. **熔断保护**:集成了熔断器,当追踪系统自身出现异常时,可以自动熔断,避免影响核心业务。 ```mermaid sequenceDiagram @@ -174,26 +203,37 @@ Beego-->>Client : HTTP 响应 ``` **Diagram sources** + - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) - [internal/controllers/base_controller.go](file://internal/controllers/base_controller.go#L1-L9) - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) **Section sources** + - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) - [internal/controllers/base_controller.go](file://internal/controllers/base_controller.go#L1-L9) - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) ### OpenTelemetry 分布式追踪分析 + `internal/otelTrace` 包负责实现系统的分布式追踪、指标和日志功能。 #### 初始化与配置 -`InitTracer` 函数在 `main.go` 中被调用,负责初始化 OpenTelemetry 的 Tracer、Meter 和 Logger Provider。它创建了 OTLP 导出器,将数据通过 gRPC 发送到后端收集器(如 Jaeger 或 Prometheus)。配置中包含了超时、重试、批量发送和 Gzip 压缩等生产环境优化选项,以确保数据传输的可靠性和效率。 + +`InitTracer` 函数在 `main.go` 中被调用,负责初始化 OpenTelemetry 的 Tracer、Meter 和 Logger Provider。它创建了 OTLP +导出器,将数据通过 gRPC 发送到后端收集器(如 Jaeger 或 Prometheus)。配置中包含了超时、重试、批量发送和 Gzip +压缩等生产环境优化选项,以确保数据传输的可靠性和效率。 #### Span 创建与上下文传递 -如上文的序列图所示,`Middleware` 函数是创建 Span 的主要入口。它使用 `otel.Tracer("gateway-router").Start` 创建一个新的服务器 Span,并通过 `propagator.Extract` 从 HTTP 请求头中提取 `traceparent` 等标准头信息,将当前 Span 与上游调用关联起来,形成完整的调用链路。 + +如上文的序列图所示,`Middleware` 函数是创建 Span 的主要入口。它使用 `otel.Tracer("gateway-router").Start` 创建一个新的服务器 +Span,并通过 `propagator.Extract` 从 HTTP 请求头中提取 `traceparent` 等标准头信息,将当前 Span 与上游调用关联起来,形成完整的调用链路。 #### 日志集成 -项目集成了 `zap` 日志库,并通过 `otelzap` 桥接器将日志与 OpenTelemetry 关联。`InitTracer` 函数中配置了 `LoggerProvider`,使得所有通过 `otelTrace.Logger` 记录的日志都会携带当前的 Span 上下文。这使得在追踪系统中可以将日志与特定的请求 Span 关联起来,极大地提升了问题排查的效率。 + +项目集成了 `zap` 日志库,并通过 `otelzap` 桥接器将日志与 OpenTelemetry 关联。`InitTracer` 函数中配置了 `LoggerProvider` +,使得所有通过 `otelTrace.Logger` 记录的日志都会携带当前的 Span 上下文。这使得在追踪系统中可以将日志与特定的请求 Span +关联起来,极大地提升了问题排查的效率。 ```mermaid classDiagram @@ -218,21 +258,29 @@ Middleware --> CustomLogger : 使用进行日志记录 ``` **Diagram sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L1-L256) - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) **Section sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L1-L256) - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) ### Redis 缓存与代理池分析 + Redis 在本项目中扮演着双重角色:通用缓存和代理池管理。 #### 缓存角色 (internal/cache) -`internal/cache/redis.go` 文件封装了一个 `RedisClient` 结构体,提供了对 Redis 的高级操作。`Start` 函数在 `main.go` 中被调用,负责根据配置初始化 Redis 连接。该模块提供了 `Set`、`Get`、`Delete` 等基本操作,以及对 Redis List 和 Stream 数据结构的封装,如 `LPush`、`RPopUnmarshal`、`XAdd`、`XReadUnmarshal` 等,方便业务层使用。`sync.Once` 确保了连接的单例模式。 + +`internal/cache/redis.go` 文件封装了一个 `RedisClient` 结构体,提供了对 Redis 的高级操作。`Start` 函数在 `main.go` +中被调用,负责根据配置初始化 Redis 连接。该模块提供了 `Set`、`Get`、`Delete` 等基本操作,以及对 Redis List 和 Stream +数据结构的封装,如 `LPush`、`RPopUnmarshal`、`XAdd`、`XReadUnmarshal` 等,方便业务层使用。`sync.Once` 确保了连接的单例模式。 #### 代理池角色 -代理池的管理也依赖于 Redis。`proxy.InitProxyPool` 函数在 `main.go` 中被调用,负责初始化代理池。虽然具体实现未在上下文中,但可以推断它会从配置中读取代理列表,并将其存储在 Redis 中(可能使用 List 或 Hash 结构),并通过 `utils.StartProxyPool` 启动一个后台任务来维护和轮询这些代理。 + +代理池的管理也依赖于 Redis。`proxy.InitProxyPool` 函数在 `main.go` 中被调用,负责初始化代理池。虽然具体实现未在上下文中,但可以推断它会从配置中读取代理列表,并将其存储在 +Redis 中(可能使用 List 或 Hash 结构),并通过 `utils.StartProxyPool` 启动一个后台任务来维护和轮询这些代理。 ```mermaid flowchart TD @@ -249,21 +297,32 @@ F --> J[代理池使用 LPush/RPop] ``` **Diagram sources** + - [main.go](file://main.go#L1-L58) - [internal/cache/redis.go](file://internal/cache/redis.go#L1-L294) **Section sources** + - [main.go](file://main.go#L1-L58) - [internal/cache/redis.go](file://internal/cache/redis.go#L1-L294) ### MySQL 与 RabbitMQ 数据访问分析 + 系统通过 Beego ORM 访问 MySQL 数据库,并通过消息队列与外部系统异步通信。 #### MySQL 与 Beego ORM -`internal/models/init.go` 文件负责初始化数据库连接。它从 `app.conf` 配置文件中读取 MySQL 的连接信息(主机、用户名、密码、数据库名),并使用 `orm.RegisterDataBase` 注册一个名为 "default" 的数据库连接。`orm.RegisterModel` 函数注册了所有需要映射到数据库表的 Go 结构体(如 `MerchantInfo`, `OrderInfo` 等)。业务代码通过 `orm.NewOrm()` 创建 ORM 实例,然后使用 `QueryTable`、`Filter`、`All`、`One` 等方法进行数据查询和操作。 + +`internal/models/init.go` 文件负责初始化数据库连接。它从 `app.conf` 配置文件中读取 MySQL 的连接信息(主机、用户名、密码、数据库名),并使用 +`orm.RegisterDataBase` 注册一个名为 "default" 的数据库连接。`orm.RegisterModel` 函数注册了所有需要映射到数据库表的 Go +结构体(如 `MerchantInfo`, `OrderInfo` 等)。业务代码通过 `orm.NewOrm()` 创建 ORM 实例,然后使用 `QueryTable`、`Filter`、 +`All`、`One` 等方法进行数据查询和操作。 #### RabbitMQ 异步消息处理 -`main.go` 文件中的 `go notify.CreateOrderNotifyConsumer(otelTrace.InitCtx)` 和 `go query.CreateSupplierOrderQueryCuConsumer(otelTrace.InitCtx)` 启动了两个后台 goroutine,分别作为 RabbitMQ 的消费者。`CreateOrderNotifyConsumer` 负责消费订单通知消息,`CreateSupplierOrderQueryCuConsumer` 负责消费供应商订单查询任务。这种异步模式解耦了核心交易流程和后续的通知/查询逻辑,提高了系统的吞吐量和响应速度。 + +`main.go` 文件中的 `go notify.CreateOrderNotifyConsumer(otelTrace.InitCtx)` 和 +`go query.CreateSupplierOrderQueryCuConsumer(otelTrace.InitCtx)` 启动了两个后台 goroutine,分别作为 RabbitMQ 的消费者。 +`CreateOrderNotifyConsumer` 负责消费订单通知消息,`CreateSupplierOrderQueryCuConsumer` +负责消费供应商订单查询任务。这种异步模式解耦了核心交易流程和后续的通知/查询逻辑,提高了系统的吞吐量和响应速度。 ```mermaid erDiagram @@ -292,15 +351,22 @@ MERCHANT_INFO ||--o{ PAYFOR_INFO : "拥有" ``` **Diagram sources** + - [internal/models/init.go](file://internal/models/init.go#L1-L56) - [main.go](file://main.go#L1-L58) **Section sources** + - [internal/models/init.go](file://internal/models/init.go#L1-L56) - [main.go](file://main.go#L1-L58) ## 依赖分析 -项目的主要依赖关系清晰地体现在 `main.go` 的初始化流程中。`main` 函数按顺序调用了 `config.GetMQAddress`、`proxy.InitProxyPool`、`otelTrace.InitTracer` 等函数,这些函数之间没有循环依赖,保证了启动的稳定性。`controllers` 依赖于 `service`,`service` 依赖于 `models` 和 `cache`,`models` 依赖于 Beego ORM,形成了一个清晰的依赖树。外部依赖包括 `github.com/beego/beego/v2`、`github.com/go-sql-driver/mysql`、`github.com/redis/go-redis/v9` 和 `go.opentelemetry.io/otel` 等。 + +项目的主要依赖关系清晰地体现在 `main.go` 的初始化流程中。`main` 函数按顺序调用了 `config.GetMQAddress`、 +`proxy.InitProxyPool`、`otelTrace.InitTracer` 等函数,这些函数之间没有循环依赖,保证了启动的稳定性。`controllers` 依赖于 +`service`,`service` 依赖于 `models` 和 `cache`,`models` 依赖于 Beego ORM,形成了一个清晰的依赖树。外部依赖包括 +`github.com/beego/beego/v2`、`github.com/go-sql-driver/mysql`、`github.com/redis/go-redis/v9` 和 +`go.opentelemetry.io/otel` 等。 ```mermaid graph TD @@ -322,33 +388,44 @@ otelTrace --> "go.opentelemetry.io/otel" ``` **Diagram sources** + - [main.go](file://main.go#L1-L58) - [internal/routers/router.go](file://internal/routers/router.go#L1-L75) **Section sources** + - [main.go](file://main.go#L1-L58) ## 性能考量 + 项目在多个层面进行了性能优化: -1. **连接池**:Beego ORM 和 Redis 客户端内部都使用了连接池,避免了频繁创建和销毁连接的开销。 -2. **异步处理**:通过 RabbitMQ 消费者异步处理订单通知和查询,避免了阻塞主请求流程。 -3. **缓存**:Redis 被用作缓存,可以显著减少对数据库的直接访问。 -4. **批量操作**:OpenTelemetry 的导出器配置了批量发送(`WithBatchTimeout`, `WithMaxExportBatchSize`),减少了网络请求次数。 -5. **熔断机制**:`otelTrace` 中间件集成了熔断器,当追踪系统过载时,可以自动降级,保障核心业务不受影响。 -6. **资源复用**:Redis 连接使用 `sync.Once` 保证单例,避免了资源浪费。 + +1. **连接池**:Beego ORM 和 Redis 客户端内部都使用了连接池,避免了频繁创建和销毁连接的开销。 +2. **异步处理**:通过 RabbitMQ 消费者异步处理订单通知和查询,避免了阻塞主请求流程。 +3. **缓存**:Redis 被用作缓存,可以显著减少对数据库的直接访问。 +4. **批量操作**:OpenTelemetry 的导出器配置了批量发送(`WithBatchTimeout`, `WithMaxExportBatchSize`),减少了网络请求次数。 +5. **熔断机制**:`otelTrace` 中间件集成了熔断器,当追踪系统过载时,可以自动降级,保障核心业务不受影响。 +6. **资源复用**:Redis 连接使用 `sync.Once` 保证单例,避免了资源浪费。 ## 故障排除指南 -* **Redis 连接失败**:检查 `app.conf` 中的 Redis 配置是否正确,确认 Redis 服务是否正常运行。查看日志中是否有 "redis 连接失败" 的错误信息。 -* **MySQL 连接失败**:检查 `app.conf` 中的 MySQL 配置(主机、端口、用户名、密码、数据库名),确认 MySQL 服务是否正常运行。查看日志中是否有 "failed to create ORM" 或类似错误。 -* **追踪数据未上报**:检查 `collectorURL` 配置是否正确,确认 OpenTelemetry Collector 服务是否正常运行。检查网络连通性。 -* **HTTP 500 错误**:查看日志中的 panic 信息或 "服务暂时不可用" 的错误,定位到具体的控制器或服务方法进行排查。 -* **慢请求告警**:在日志中搜索 "慢请求检测",分析具体是哪个接口或哪段代码导致了性能瓶颈。 + +* **Redis 连接失败**:检查 `app.conf` 中的 Redis 配置是否正确,确认 Redis 服务是否正常运行。查看日志中是否有 "redis + 连接失败" 的错误信息。 +* **MySQL 连接失败**:检查 `app.conf` 中的 MySQL 配置(主机、端口、用户名、密码、数据库名),确认 MySQL + 服务是否正常运行。查看日志中是否有 "failed to create ORM" 或类似错误。 +* **追踪数据未上报**:检查 `collectorURL` 配置是否正确,确认 OpenTelemetry Collector 服务是否正常运行。检查网络连通性。 +* **HTTP 500 错误**:查看日志中的 panic 信息或 "服务暂时不可用" 的错误,定位到具体的控制器或服务方法进行排查。 +* **慢请求告警**:在日志中搜索 "慢请求检测",分析具体是哪个接口或哪段代码导致了性能瓶颈。 **Section sources** + - [internal/cache/redis.go](file://internal/cache/redis.go#L1-L294) - [internal/models/init.go](file://internal/models/init.go#L1-L56) - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L1-L256) - [internal/otelTrace/middleware.go](file://internal/otelTrace/middleware.go#L1-L141) ## 结论 -`kami_gateway` 项目构建了一个技术栈选型合理、架构清晰的微服务网关。通过 Beego v2 框架提供了稳定高效的 Web 服务,OpenTelemetry 实现了全面的可观测性,Redis 和 MySQL 分别承担了缓存和持久化存储的角色,RabbitMQ 则保证了系统的异步解耦。各组件通过 `main.go` 文件被有序地集成和启动,形成了一个高可用、高性能、易于维护的系统。遵循文档中提到的配置最佳实践,可以确保系统在生产环境中的稳定运行。 \ No newline at end of file + +`kami_gateway` 项目构建了一个技术栈选型合理、架构清晰的微服务网关。通过 Beego v2 框架提供了稳定高效的 Web 服务,OpenTelemetry +实现了全面的可观测性,Redis 和 MySQL 分别承担了缓存和持久化存储的角色,RabbitMQ 则保证了系统的异步解耦。各组件通过 +`main.go` 文件被有序地集成和启动,形成了一个高可用、高性能、易于维护的系统。遵循文档中提到的配置最佳实践,可以确保系统在生产环境中的稳定运行。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/MySQL数据库集成.md b/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/MySQL数据库集成.md index 81d86a9..4085a1f 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/MySQL数据库集成.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/MySQL数据库集成.md @@ -9,6 +9,7 @@ ## 目录 + 1. [数据库初始化流程](#数据库初始化流程) 2. [配置文件解析](#配置文件解析) 3. [ORM模型注册机制](#orm模型注册机制) @@ -19,7 +20,9 @@ ## 数据库初始化流程 -系统在启动时通过`internal/models/init.go`文件中的`init`函数完成MySQL数据库的初始化配置。该函数在程序启动时自动执行,负责从配置文件读取数据库连接参数,构造连接字符串,并完成Beego ORM的注册与配置。 +系统在启动时通过`internal/models/init.go`文件中的`init` +函数完成MySQL数据库的初始化配置。该函数在程序启动时自动执行,负责从配置文件读取数据库连接参数,构造连接字符串,并完成Beego +ORM的注册与配置。 ```mermaid flowchart TD @@ -34,14 +37,17 @@ RegisterModels --> End([数据库初始化完成]) ``` **Diagram sources** + - [internal/models/init.go](file://internal/models/init.go#L22-L56) **Section sources** + - [internal/models/init.go](file://internal/models/init.go#L1-L56) ## 配置文件解析 -数据库连接参数从`conf/app.conf`配置文件中读取,采用分段式配置结构。系统通过Beego框架提供的`web.AppConfig`接口获取配置值,确保了配置管理的统一性和灵活性。 +数据库连接参数从`conf/app.conf`配置文件中读取,采用分段式配置结构。系统通过Beego框架提供的`web.AppConfig` +接口获取配置值,确保了配置管理的统一性和灵活性。 ```ini [mysql] @@ -54,6 +60,7 @@ debug = true ``` 配置项说明: + - **dbhost**: 数据库服务器地址 - **dbport**: 数据库服务端口 - **dbuser**: 数据库用户名 @@ -64,12 +71,14 @@ debug = true 系统使用`web.AppConfig.String()`方法读取字符串类型配置,使用`web.AppConfig.DefaultBool()`方法读取布尔类型配置并提供默认值。 **Section sources** + - [conf/app.conf](file://conf/app.conf#L40-L47) - [internal/models/init.go](file://internal/models/init.go#L22-L30) ## ORM模型注册机制 -Beego ORM通过`RegisterModel`函数注册所有需要映射到数据库表的实体模型。系统采用集中式注册方式,在`init`函数中一次性注册所有模型,确保了模型管理的统一性。 +Beego ORM通过`RegisterModel`函数注册所有需要映射到数据库表的实体模型。系统采用集中式注册方式,在`init` +函数中一次性注册所有模型,确保了模型管理的统一性。 ```mermaid classDiagram @@ -128,11 +137,13 @@ NotifyInfo --> OrderInfo : "notifies" ``` **Diagram sources** + - [internal/models/init.go](file://internal/models/init.go#L48-L55) - [internal/models/order/order_info.go](file://internal/models/order/order_info.go#L19-L68) - [internal/models/merchant/merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) **Section sources** + - [internal/models/init.go](file://internal/models/init.go#L48-L55) ## 数据库连接池管理 @@ -140,11 +151,13 @@ NotifyInfo --> OrderInfo : "notifies" 系统通过Beego ORM的`RegisterDataBase`函数建立数据库连接池,使用标准的MySQL连接字符串格式。连接池配置支持自动连接恢复和连接复用,提高了数据库访问效率。 连接字符串构造逻辑: + ``` 用户名:密码@tcp(主机:端口)/数据库名?charset=utf8&loc=Local&parseTime=true ``` 关键参数说明: + - **charset=utf8**: 指定字符集为UTF-8,支持中文存储 - **loc=Local**: 设置时区为本地时区 - **parseTime=true**: 启用时间类型自动解析 @@ -152,17 +165,20 @@ NotifyInfo --> OrderInfo : "notifies" 系统还通过`orm.Debug`开关控制SQL日志输出,便于开发调试和性能分析。 **Section sources** + - [internal/models/init.go](file://internal/models/init.go#L32-L40) ## 实体模型结构 -系统定义了多个实体模型来管理不同的业务数据,每个模型对应数据库中的一张表。模型采用Go语言的结构体定义,通过字段标签和Beego ORM约定实现数据库映射。 +系统定义了多个实体模型来管理不同的业务数据,每个模型对应数据库中的一张表。模型采用Go语言的结构体定义,通过字段标签和Beego +ORM约定实现数据库映射。 ### 订单信息模型 `OrderInfo`结构体定义了订单相关的核心数据字段,包括订单标识、金额信息、状态跟踪和时间戳等。 **Section sources** + - [internal/models/order/order_info.go](file://internal/models/order/order_info.go#L19-L68) ### 商户信息模型 @@ -170,6 +186,7 @@ NotifyInfo --> OrderInfo : "notifies" `MerchantInfo`结构体管理商户的基本信息、认证凭证和业务配置,是系统权限控制和业务处理的基础。 **Section sources** + - [internal/models/merchant/merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) ## 数据操作实践 @@ -194,6 +211,7 @@ Service-->>调用方 : 返回业务数据 ``` **Diagram sources** + - [internal/models/order/order_info.go](file://internal/models/order/order_info.go#L100-L120) - [internal/models/merchant/merchant_info.go](file://internal/models/merchant/merchant_info.go#L90-L110) @@ -202,6 +220,7 @@ Service-->>调用方 : 返回业务数据 系统通过`Insert`或`InsertWithCtx`方法实现数据插入,支持上下文传递以实现请求链路追踪。 **Section sources** + - [internal/models/order/order_info.go](file://internal/models/order/order_info.go#L150-L160) - [internal/models/merchant/merchant_info.go](file://internal/models/merchant/merchant_info.go#L170-L180) @@ -210,6 +229,7 @@ Service-->>调用方 : 返回业务数据 采用`Update`或`UpdateWithCtx`方法进行数据更新,支持批量更新和条件更新,确保了数据一致性。 **Section sources** + - [internal/models/order/order_info.go](file://internal/models/order/order_info.go#L130-L140) - [internal/models/merchant/merchant_info.go](file://internal/models/merchant/merchant_info.go#L200-L210) @@ -218,6 +238,7 @@ Service-->>调用方 : 返回业务数据 ### 索引设计策略 根据业务查询模式,在高频查询字段上创建索引: + - 订单表:`bank_order_id`, `merchant_order_id`, `create_time`, `status` - 商户表:`merchant_uid`, `login_account`, `belong_agent_uid` - 通道表:`road_uid`, `pay_product_code` @@ -225,6 +246,7 @@ Service-->>调用方 : 返回业务数据 ### 连接池调优 建议根据实际并发量调整连接池参数: + - 设置合理的最大连接数(MaxOpenConns) - 配置适当的空闲连接数(MaxIdleConns) - 设置连接生命周期(ConnMaxLifetime) diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/Redis缓存系统.md b/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/Redis缓存系统.md index f9053fc..2c3da8a 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/Redis缓存系统.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/Redis缓存系统.md @@ -10,6 +10,7 @@ ## 目录 + 1. [Redis双重角色概述](#redis双重角色概述) 2. [单例初始化流程](#单例初始化流程) 3. [分布式缓存应用](#分布式缓存应用) @@ -23,17 +24,22 @@ Redis在系统中扮演着双重关键角色:作为分布式缓存层处理高频数据访问,以及作为代理池的状态存储中心。这种双重架构设计实现了数据访问加速与代理资源管理的统一。 -作为分布式缓存层,Redis被广泛应用于订单状态缓存、商户配置缓存等高频读取场景,有效降低了数据库的访问压力。同时,Redis作为代理池的状态存储,通过`internal/utils/dm_proxy_strategy.go`中的`DMProxyStrategy`结构体,将代理IP、过期时间、最后使用时间等关键信息持久化存储在Redis中,实现了代理资源的集中管理和状态追踪。 +作为分布式缓存层,Redis被广泛应用于订单状态缓存、商户配置缓存等高频读取场景,有效降低了数据库的访问压力。同时,Redis作为代理池的状态存储,通过 +`internal/utils/dm_proxy_strategy.go`中的`DMProxyStrategy`结构体,将代理IP、过期时间、最后使用时间等关键信息持久化存储在Redis中,实现了代理资源的集中管理和状态追踪。 **Section sources** + - [dm_proxy_strategy.go](file://internal/utils/dm_proxy_strategy.go#L38-L43) - [proxy_pool.go](file://internal/utils/proxy_pool.go#L537-L553) ## 单例初始化流程 -Redis客户端的初始化通过`internal/cache/redis.go`中的`Start()`函数实现,采用`sync.OnceFunc`确保线程安全的单例模式。该流程严格遵循一次性初始化原则,防止并发环境下重复创建连接实例。 +Redis客户端的初始化通过`internal/cache/redis.go`中的`Start()`函数实现,采用`sync.OnceFunc` +确保线程安全的单例模式。该流程严格遵循一次性初始化原则,防止并发环境下重复创建连接实例。 -初始化过程首先从配置中心获取Redis连接参数,包括主机地址、密码和数据库编号。这些参数通过`config.GetConfig().GetRedisConfig()`方法从`conf/app.conf`文件中读取,其中默认配置为主机`127.0.0.1:6379`,数据库`db=0`,密码为空字符串。 +初始化过程首先从配置中心获取Redis连接参数,包括主机地址、密码和数据库编号。这些参数通过 +`config.GetConfig().GetRedisConfig()`方法从`conf/app.conf`文件中读取,其中默认配置为主机`127.0.0.1:6379`,数据库`db=0` +,密码为空字符串。 ```mermaid sequenceDiagram @@ -50,11 +56,13 @@ cache-->>main : 初始化完成 ``` **Diagram sources** + - [redis.go](file://internal/cache/redis.go#L13-L25) - [cfg_model.go](file://internal/config/cfg_model.go#L127-L133) - [app.conf](file://conf/app.conf#L60-L63) **Section sources** + - [redis.go](file://internal/cache/redis.go#L13-L30) - [cfg_model.go](file://internal/config/cfg_model.go#L127-L133) @@ -62,21 +70,27 @@ cache-->>main : 初始化完成 Redis作为分布式缓存层,在系统中支撑着多个核心业务场景的数据访问。通过`GetRedisClient()`函数提供的全局访问点,各业务模块可以高效地进行缓存操作。 -在订单管理场景中,系统利用Redis的List数据结构实现订单队列管理,通过`LPush`和`RPopUnmarshal`等方法进行订单的入队和出队操作。对于商户配置信息,采用Hash结构进行存储,实现配置项的快速读取和更新。高频访问的静态数据如支付通道信息,通过`Set`和`Get`方法进行缓存,显著提升了接口响应速度。 +在订单管理场景中,系统利用Redis的List数据结构实现订单队列管理,通过`LPush`和`RPopUnmarshal` +等方法进行订单的入队和出队操作。对于商户配置信息,采用Hash结构进行存储,实现配置项的快速读取和更新。高频访问的静态数据如支付通道信息,通过 +`Set`和`Get`方法进行缓存,显著提升了接口响应速度。 缓存策略采用合理的过期时间设置,避免数据长期驻留导致内存浪费。同时,通过`Exists`方法实现缓存预热和缓存击穿的预防,确保系统在高并发场景下的稳定性。 **Section sources** + - [redis.go](file://internal/cache/redis.go#L70-L100) - [redis.go](file://internal/cache/redis.go#L134-L183) ## 代理池状态存储 -Redis在代理池管理中发挥着核心作用,通过与`internal/utils/proxy_pool.go`和`internal/utils/dm_proxy_strategy.go`的深度集成,实现了代理资源的智能化管理。 +Redis在代理池管理中发挥着核心作用,通过与`internal/utils/proxy_pool.go`和`internal/utils/dm_proxy_strategy.go` +的深度集成,实现了代理资源的智能化管理。 -`DMProxyStrategy`结构体直接持有`*redis.Client`引用,将Redis作为代理状态的唯一事实来源。代理IP、过期时间、最后使用时间等信息以`DMProxyInfo`结构体形式序列化后存储在Redis中,键名为`proxy:{ip}`。这种设计实现了代理状态的持久化,即使服务重启也能恢复代理池状态。 +`DMProxyStrategy`结构体直接持有`*redis.Client`引用,将Redis作为代理状态的唯一事实来源。代理IP、过期时间、最后使用时间等信息以 +`DMProxyInfo`结构体形式序列化后存储在Redis中,键名为`proxy:{ip}`。这种设计实现了代理状态的持久化,即使服务重启也能恢复代理池状态。 -代理池的清理机制通过定时任务实现,`startCleanupRoutine`协程每分钟执行一次`cleanupExpiredProxies`,清除过期的代理记录。同时,`ensureProxyPool`方法确保代理池中始终有足够的可用代理,当数量低于阈值时自动从代理服务商拉取新代理。 +代理池的清理机制通过定时任务实现,`startCleanupRoutine`协程每分钟执行一次`cleanupExpiredProxies`,清除过期的代理记录。同时, +`ensureProxyPool`方法确保代理池中始终有足够的可用代理,当数量低于阈值时自动从代理服务商拉取新代理。 ```mermaid classDiagram @@ -105,34 +119,44 @@ DMProxyStrategy --> redis.Client : "状态存储" ``` **Diagram sources** + - [dm_proxy_strategy.go](file://internal/utils/dm_proxy_strategy.go#L38-L43) - [dm_proxy_strategy.go](file://internal/utils/dm_proxy_strategy.go#L11-L18) **Section sources** + - [dm_proxy_strategy.go](file://internal/utils/dm_proxy_strategy.go#L35-L377) - [proxy_pool.go](file://internal/utils/proxy_pool.go#L537-L553) ## 键值设计与序列化 -系统采用规范化的键值设计原则,确保Redis数据的可维护性和可追溯性。键名遵循`domain:subdomain:identifier`的命名规范,如订单相关的键以`order:`为前缀,代理相关的键以`proxy:`为前缀。 +系统采用规范化的键值设计原则,确保Redis数据的可维护性和可追溯性。键名遵循`domain:subdomain:identifier`的命名规范,如订单相关的键以 +`order:`为前缀,代理相关的键以`proxy:`为前缀。 -序列化策略根据数据类型和使用场景进行优化。对于结构体数据,采用JSON序列化,通过`json.Marshal`和`json.Unmarshal`实现对象的持久化。对于简单类型数据,直接使用Redis原生的字符串存储。在List和Stream操作中,系统自动将复杂对象序列化为JSON字符串后存储,确保数据的完整性和可读性。 +序列化策略根据数据类型和使用场景进行优化。对于结构体数据,采用JSON序列化,通过`json.Marshal`和`json.Unmarshal` +实现对象的持久化。对于简单类型数据,直接使用Redis原生的字符串存储。在List和Stream操作中,系统自动将复杂对象序列化为JSON字符串后存储,确保数据的完整性和可读性。 -特殊数据类型如时间戳采用Unix时间戳存储,避免时区问题。布尔值通过`"true"`和`"false"`字符串表示,确保跨语言兼容性。这种统一的序列化策略简化了数据访问逻辑,降低了维护成本。 +特殊数据类型如时间戳采用Unix时间戳存储,避免时区问题。布尔值通过`"true"`和`"false"` +字符串表示,确保跨语言兼容性。这种统一的序列化策略简化了数据访问逻辑,降低了维护成本。 **Section sources** + - [redis.go](file://internal/cache/redis.go#L134-L183) - [redis.go](file://internal/cache/redis.go#L224-L275) ## 连接池与性能配置 -Redis客户端配置了合理的连接池参数,以平衡性能和资源消耗。虽然当前实现中未显式设置连接池大小,但依赖于`github.com/redis/go-redis/v9`库的默认连接池行为。 +Redis客户端配置了合理的连接池参数,以平衡性能和资源消耗。虽然当前实现中未显式设置连接池大小,但依赖于 +`github.com/redis/go-redis/v9`库的默认连接池行为。 -连接超时、读取超时和写入超时均设置为合理的默认值,确保在网络异常时能够快速失败,避免请求堆积。通过`Ping()`方法在初始化时进行连接测试,确保Redis服务的可用性。 +连接超时、读取超时和写入超时均设置为合理的默认值,确保在网络异常时能够快速失败,避免请求堆积。通过`Ping()` +方法在初始化时进行连接测试,确保Redis服务的可用性。 -在高并发场景下,系统利用Redis管道(Pipeline)和事务管道(TxPipeline)功能,通过`Pipeline()`和`TxPipeline()`方法减少网络往返次数,提升批量操作的性能。发布/订阅模式通过`Publish()`和`Subscribe()`方法实现,支持实时消息通知。 +在高并发场景下,系统利用Redis管道(Pipeline)和事务管道(TxPipeline)功能,通过`Pipeline()`和`TxPipeline()` +方法减少网络往返次数,提升批量操作的性能。发布/订阅模式通过`Publish()`和`Subscribe()`方法实现,支持实时消息通知。 **Section sources** + - [redis.go](file://internal/cache/redis.go#L35-L50) - [redis.go](file://internal/cache/redis.go#L290-L300) @@ -140,13 +164,17 @@ Redis客户端配置了合理的连接池参数,以平衡性能和资源消耗 系统实现了多层次的缓存防护机制,有效应对缓存穿透、缓存击穿和缓存雪崩等常见问题。 -对于缓存穿透,系统在数据访问层进行参数校验,拒绝非法请求。同时,对于查询结果为空的情况,设置短时间的空值缓存,避免相同请求频繁穿透到数据库。通过`Exists`方法预先检查键的存在性,减少不必要的查询操作。 +对于缓存穿透,系统在数据访问层进行参数校验,拒绝非法请求。同时,对于查询结果为空的情况,设置短时间的空值缓存,避免相同请求频繁穿透到数据库。通过 +`Exists`方法预先检查键的存在性,减少不必要的查询操作。 -缓存击穿通过合理的过期时间设置和互斥锁机制防范。虽然当前代码中未显式实现分布式锁,但`sync.OnceFunc`的单例模式为关键初始化操作提供了线程安全保证。在热点数据更新时,采用先更新缓存后更新数据库的策略,确保数据一致性。 +缓存击穿通过合理的过期时间设置和互斥锁机制防范。虽然当前代码中未显式实现分布式锁,但`sync.OnceFunc` +的单例模式为关键初始化操作提供了线程安全保证。在热点数据更新时,采用先更新缓存后更新数据库的策略,确保数据一致性。 -监控方面,系统通过`GetSize()`和`GetSizeByPrefix()`方法定期采集Redis内存使用情况,为容量规划提供数据支持。错误日志通过`otelTrace.Logger`记录,便于问题排查和性能分析。 +监控方面,系统通过`GetSize()`和`GetSizeByPrefix()`方法定期采集Redis内存使用情况,为容量规划提供数据支持。错误日志通过 +`otelTrace.Logger`记录,便于问题排查和性能分析。 **Section sources** + - [redis.go](file://internal/cache/redis.go#L102-L115) - [redis.go](file://internal/cache/redis.go#L117-L125) @@ -156,10 +184,12 @@ Redis客户端配置了合理的连接池参数,以平衡性能和资源消耗 健康检查通过`Ping()`方法实现,定期验证Redis连接的可用性。在`Start()`函数中,连接失败时会记录详细的错误日志,包括错误类型和堆栈信息,为故障排查提供依据。 -运维方面,系统提供了`Delete()`方法用于手动清理缓存,`Expire()`方法用于动态调整键的过期时间。通过`Keys()`方法配合前缀查询,可以统计特定类型数据的数量,为容量规划和性能优化提供数据支持。 +运维方面,系统提供了`Delete()`方法用于手动清理缓存,`Expire()`方法用于动态调整键的过期时间。通过`Keys()` +方法配合前缀查询,可以统计特定类型数据的数量,为容量规划和性能优化提供数据支持。 定期的清理任务通过协程实现,如代理池的`startCleanupRoutine`,确保过期数据能够及时清理,避免内存泄漏。这种主动式运维策略提高了系统的自愈能力,降低了人工干预的需求。 **Section sources** + - [redis.go](file://internal/cache/redis.go#L13-L30) - [dm_proxy_strategy.go](file://internal/utils/dm_proxy_strategy.go#L251-L263) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/数据库与缓存系统.md b/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/数据库与缓存系统.md index 664041e..9894249 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/数据库与缓存系统.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/数据库与缓存系统/数据库与缓存系统.md @@ -12,6 +12,7 @@ ## 目录 + 1. [项目结构](#项目结构) 2. [MySQL 数据库集成与 ORM 配置](#mysql-数据库集成与-orm-配置) 3. [Beego ORM 模型定义与自动迁移](#beego-orm-模型定义与自动迁移) @@ -27,7 +28,8 @@ ## 项目结构 -本项目采用分层架构设计,核心数据持久化与缓存组件集中于 `internal` 目录下。`models` 目录存放所有数据库实体模型,`cache` 目录封装 Redis 客户端,`proxy` 和 `utils` 目录分别实现代理池的两种状态存储方案。 +本项目采用分层架构设计,核心数据持久化与缓存组件集中于 `internal` 目录下。`models` 目录存放所有数据库实体模型,`cache` 目录封装 +Redis 客户端,`proxy` 和 `utils` 目录分别实现代理池的两种状态存储方案。 ```mermaid graph TD @@ -57,13 +59,15 @@ Cache --> Utils ``` **图源** + - [conf/app.conf](file://conf/app.conf) - [internal/models/init.go](file://internal/models/init.go) - [internal/cache/redis.go](file://internal/cache/redis.go) ## MySQL 数据库集成与 ORM 配置 -系统通过 Beego ORM 框架集成 MySQL 数据库,使用 `github.com/go-sql-driver/mysql` 作为底层驱动。数据库连接信息从 `conf/app.conf` 文件中读取,并在程序启动时完成初始化。 +系统通过 Beego ORM 框架集成 MySQL 数据库,使用 `github.com/go-sql-driver/mysql` 作为底层驱动。数据库连接信息从 +`conf/app.conf` 文件中读取,并在程序启动时完成初始化。 ```mermaid sequenceDiagram @@ -84,16 +88,19 @@ ORM->>MySQL : 建立连接 ``` **图源** + - [internal/models/init.go](file://internal/models/init.go#L21-L55) - [conf/app.conf](file://conf/app.conf#L15-L21) **本节源码** + - [internal/models/init.go](file://internal/models/init.go#L21-L55) - [conf/app.conf](file://conf/app.conf#L15-L21) ## Beego ORM 模型定义与自动迁移 -`models` 目录下的各子包(如 `accounts`, `merchant`, `order` 等)定义了具体的数据库实体。每个实体结构体通过 `orm.RegisterModel()` 在 `init()` 函数中注册,Beego ORM 会根据结构体字段自动生成对应的数据库表。 +`models` 目录下的各子包(如 `accounts`, `merchant`, `order` 等)定义了具体的数据库实体。每个实体结构体通过 +`orm.RegisterModel()` 在 `init()` 函数中注册,Beego ORM 会根据结构体字段自动生成对应的数据库表。 ```mermaid classDiagram @@ -148,6 +155,7 @@ PayforInfo --> BankCardInfo : "关联银行卡" ``` **图源** + - [internal/models/user/user_info.go](file://internal/models/user/user_info.go) - [internal/models/merchant/merchant_info.go](file://internal/models/merchant/merchant_info.go) - [internal/models/order/order_info.go](file://internal/models/order/order_info.go) @@ -157,7 +165,8 @@ PayforInfo --> BankCardInfo : "关联银行卡" ## 事务处理模式 -系统通过 Beego ORM 的 `orm.NewOrm()` 方法获取事务对象,支持显式事务控制。在需要保证数据一致性的业务场景(如订单创建、资金变动)中,使用 `Begin()`、`Commit()` 和 `Rollback()` 方法管理事务。 +系统通过 Beego ORM 的 `orm.NewOrm()` 方法获取事务对象,支持显式事务控制。在需要保证数据一致性的业务场景(如订单创建、资金变动)中,使用 +`Begin()`、`Commit()` 和 `Rollback()` 方法管理事务。 ```mermaid flowchart TD @@ -172,11 +181,13 @@ Rollback --> End ``` **本节源码** + - [internal/models/init.go](file://internal/models/init.go#L21-L55) ## Redis 缓存系统架构 -Redis 在系统中扮演双重角色:作为 `internal/cache` 的分布式缓存层,加速高频数据读取;作为 `internal/utils/proxy_pool.go` 中代理池的状态存储,管理代理IP的生命周期。 +Redis 在系统中扮演双重角色:作为 `internal/cache` 的分布式缓存层,加速高频数据读取;作为 `internal/utils/proxy_pool.go` +中代理池的状态存储,管理代理IP的生命周期。 ```mermaid graph TB @@ -198,12 +209,14 @@ ProxyPool --> |状态存储| RedisServer ``` **图源** + - [internal/cache/redis.go](file://internal/cache/redis.go) - [internal/utils/proxy_pool.go](file://internal/utils/proxy_pool.go) ## Redis 初始化与连接池管理 -Redis 客户端通过 `cache.Start()` 函数进行单例初始化。该函数使用 `sync.OnceFunc` 确保全局唯一实例,从配置中读取连接参数,并建立与 Redis 服务器的连接。 +Redis 客户端通过 `cache.Start()` 函数进行单例初始化。该函数使用 `sync.OnceFunc` 确保全局唯一实例,从配置中读取连接参数,并建立与 +Redis 服务器的连接。 ```mermaid sequenceDiagram @@ -226,16 +239,19 @@ end ``` **图源** + - [internal/cache/redis.go](file://internal/cache/redis.go#L18-L28) - [internal/config/cfg_model.go](file://internal/config/cfg_model.go#L128-L138) **本节源码** + - [internal/cache/redis.go](file://internal/cache/redis.go#L18-L28) - [internal/config/cfg_model.go](file://internal/config/cfg_model.go#L128-L138) ## 分布式缓存层设计 -`internal/cache` 包提供了一个封装的 `RedisClient` 结构体,对 `github.com/redis/go-redis/v9` 客户端进行了二次封装,提供了更便捷的 API。该层支持字符串、列表、Stream 等多种数据结构的操作,并内置了序列化/反序列化功能。 +`internal/cache` 包提供了一个封装的 `RedisClient` 结构体,对 `github.com/redis/go-redis/v9` 客户端进行了二次封装,提供了更便捷的 +API。该层支持字符串、列表、Stream 等多种数据结构的操作,并内置了序列化/反序列化功能。 ```mermaid classDiagram @@ -258,11 +274,14 @@ RedisClient 的使用 --> ProxyPool : "代理状态" ``` **图源** + - [internal/cache/redis.go](file://internal/cache/redis.go#L35-L37) ## 代理池状态存储机制 -`internal/utils/proxy_pool.go` 实现了一个基于订单号和通道的代理策略(`OrderBasedProxyStrategy`)。它使用内存中的 `map[string]*ProxyInfo` 来缓存代理IP,并通过 `StartProxyPool()` 函数启动。该策略支持跨通道复用代理IP,以满足 `OrderPerIP` 配置的需求。 +`internal/utils/proxy_pool.go` 实现了一个基于订单号和通道的代理策略(`OrderBasedProxyStrategy`)。它使用内存中的 +`map[string]*ProxyInfo` 来缓存代理IP,并通过 `StartProxyPool()` 函数启动。该策略支持跨通道复用代理IP,以满足 `OrderPerIP` +配置的需求。 ```mermaid flowchart TD @@ -279,47 +298,57 @@ ReturnNew --> End ``` **图源** + - [internal/utils/proxy_pool.go](file://internal/utils/proxy_pool.go#L100-L150) **本节源码** + - [internal/utils/proxy_pool.go](file://internal/utils/proxy_pool.go#L100-L150) ## 键值设计规范 系统遵循清晰的键值命名规范,以确保数据的可维护性和可读性。Redis 键通常采用 `domain:subdomain:identifier` 的格式。 -| 键前缀 | 用途 | 示例 | TTL | -| :--- | :--- | :--- | :--- | -| `nuclear_random_ids:` | 核弹卡密的随机ID与指纹映射 | `nuclear_random_ids:abc123` | 永久 (0) | -| `channel_orderID` | 代理池缓存键 | `appleCard_order_123` | 50-55秒 | -| `customer_order_pool:` | 用户订单池 | `customer_order_pool:road123:100.00` | 动态 | -| `produce_order_pool:` | 供应订单池 | `produce_order_pool:road123:100.00` | 动态 | +| 键前缀 | 用途 | 示例 | TTL | +|:-----------------------|:---------------|:-------------------------------------|:-------| +| `nuclear_random_ids:` | 核弹卡密的随机ID与指纹映射 | `nuclear_random_ids:abc123` | 永久 (0) | +| `channel_orderID` | 代理池缓存键 | `appleCard_order_123` | 50-55秒 | +| `customer_order_pool:` | 用户订单池 | `customer_order_pool:road123:100.00` | 动态 | +| `produce_order_pool:` | 供应订单池 | `produce_order_pool:road123:100.00` | 动态 | **本节源码** + - [internal/service/supplier/third_party/pool/card_sender/nuclear.go](file://internal/service/supplier/third_party/pool/card_sender/nuclear.go#L48) - [internal/utils/proxy_pool.go](file://internal/utils/proxy_pool.go#L100) ## 数据库连接管理 -数据库连接由 Beego ORM 在 `init()` 函数中统一管理。通过 `RegisterDataBase()` 注册默认数据库连接,并使用全局的 `orm.Debug` 标志控制SQL日志输出。所有数据访问操作都通过 `orm.NewOrm()` 获取的 ORM 实例进行。 +数据库连接由 Beego ORM 在 `init()` 函数中统一管理。通过 `RegisterDataBase()` 注册默认数据库连接,并使用全局的 `orm.Debug` +标志控制SQL日志输出。所有数据访问操作都通过 `orm.NewOrm()` 获取的 ORM 实例进行。 **本节源码** + - [internal/models/init.go](file://internal/models/init.go#L21-L55) ## 缓存穿透与击穿应对策略 系统通过以下策略应对缓存问题: + - **缓存穿透**:对于 `nuclear_random_ids` 这类键,即使Redis中不存在,也会生成一个临时ID和指纹作为兜底,避免大量请求直接打到数据库。 -- **缓存击穿**:`OrderBasedProxyStrategy` 使用 `sync.RWMutex` 对 `proxies` 映射进行读写保护,在获取新代理时加写锁,确保并发安全,防止同一时间大量请求穿透到代理服务API。 +- **缓存击穿**:`OrderBasedProxyStrategy` 使用 `sync.RWMutex` 对 `proxies` + 映射进行读写保护,在获取新代理时加写锁,确保并发安全,防止同一时间大量请求穿透到代理服务API。 **本节源码** + - [internal/service/supplier/third_party/pool/card_sender/nuclear.go](file://internal/service/supplier/third_party/pool/card_sender/nuclear.go#L81) - [internal/utils/proxy_pool.go](file://internal/utils/proxy_pool.go#L100) ## 性能监控指标 -系统通过 `otelTrace` 模块集成 OpenTelemetry,对关键操作进行监控。日志中记录了代理获取、Redis操作、数据库查询等耗时,可用于分析性能瓶颈。例如,`GetProxy` 函数被标记为一个Span,可以追踪其执行时间。 +系统通过 `otelTrace` 模块集成 OpenTelemetry,对关键操作进行监控。日志中记录了代理获取、Redis操作、数据库查询等耗时,可用于分析性能瓶颈。例如, +`GetProxy` 函数被标记为一个Span,可以追踪其执行时间。 **本节源码** + - [internal/utils/proxy_pool.go](file://internal/utils/proxy_pool.go#L301) - [internal/cache/redis.go](file://internal/cache/redis.go) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/技术栈与依赖/消息队列与异步处理.md b/.qoder/repowiki/zh/content/技术栈与依赖/消息队列与异步处理.md index 159a1c4..bb50eec 100644 --- a/.qoder/repowiki/zh/content/技术栈与依赖/消息队列与异步处理.md +++ b/.qoder/repowiki/zh/content/技术栈与依赖/消息队列与异步处理.md @@ -13,6 +13,7 @@ ## 目录 + 1. [引言](#引言) 2. [核心组件与架构](#核心组件与架构) 3. [消息消费者启动流程](#消息消费者启动流程) @@ -25,10 +26,14 @@ 10. [事件解耦与业务流程](#事件解耦与业务流程) ## 引言 -本文档详细描述了 `kami_gateway` 系统中基于 RabbitMQ 的异步任务处理机制。系统通过 `github.com/go-stomp/stomp/v3` 客户端实现消息队列通信,采用消息队列解耦核心支付流程,提升系统响应性与可扩展性。重点分析订单通知、渠道查询等关键事件的异步处理流程,并深入探讨队列管理器、任务处理器与工作协程之间的协作机制。 + +本文档详细描述了 `kami_gateway` 系统中基于 RabbitMQ 的异步任务处理机制。系统通过 `github.com/go-stomp/stomp/v3` +客户端实现消息队列通信,采用消息队列解耦核心支付流程,提升系统响应性与可扩展性。重点分析订单通知、渠道查询等关键事件的异步处理流程,并深入探讨队列管理器、任务处理器与工作协程之间的协作机制。 ## 核心组件与架构 + 系统通过 ActiveMQ(兼容 STOMP 协议)作为消息中间件,结合 Redis 队列与 Go 协程池实现多层级异步任务处理。主要组件包括: + - **消息生产者**:通过 `SendMessage` 发布订单通知与查询请求 - **消息消费者**:`CreateOrderNotifyConsumer` 与 `CreateSupplierOrderQueryCuConsumer` 监听队列 - **队列管理器**:`QueueManager` 统一管理 Redis 队列生命周期 @@ -62,28 +67,38 @@ BusinessLogic --> |结果| OrderNotify BusinessLogic --> |结果| SupplierQuery ``` -**图示来源** +**图示来源** + - [manager.go](file://internal/service/supplier/third_party/queue/manager.go) - [handlers.go](file://internal/service/supplier/third_party/queue/handlers.go) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go) ## 消息消费者启动流程 + 系统在初始化阶段启动多个消息消费者,分别监听不同的主题队列。 ### 订单通知消费者 -`CreateOrderNotifyConsumer` 函数负责启动订单回调消息的监听。首先获取 ActiveMQ 连接,订阅 `order_notify` 队列,采用 `stomp.AckClient` 模式手动确认消息。一旦接收到消息,立即通过 `sendNotifyPool.Go` 提交至异步协程池处理,并立即执行 `Ack` 确认,确保消息不丢失。 + +`CreateOrderNotifyConsumer` 函数负责启动订单回调消息的监听。首先获取 ActiveMQ 连接,订阅 `order_notify` 队列,采用 +`stomp.AckClient` 模式手动确认消息。一旦接收到消息,立即通过 `sendNotifyPool.Go` 提交至异步协程池处理,并立即执行 `Ack` +确认,确保消息不丢失。 ### 渠道查询消费者 -`CreateSupplierOrderQueryCuConsumer` 启动订单查询任务的消费者,订阅 `order_query` 队列。接收到消息后,解析 `bankOrderId`,创建包含定时器的 `OrderQueryTask`,并将其加入延迟查询队列,随后立即确认消息。 -**章节来源** +`CreateSupplierOrderQueryCuConsumer` 启动订单查询任务的消费者,订阅 `order_query` 队列。接收到消息后,解析 `bankOrderId` +,创建包含定时器的 `OrderQueryTask`,并将其加入延迟查询队列,随后立即确认消息。 + +**章节来源** + - [order_notify.go](file://internal/service/notify/order_notify.go#L185-L217) - [supplier_query.go](file://internal/schema/query/supplier_query.go#L89-L116) ## 消息监听与处理机制 + 消费者采用 `for range` 或 `select` 循环持续监听消息通道。所有消息体为 `bankOrderId` 字符串,消费者不进行复杂解析,仅提取订单号后触发后续异步流程。 消息处理采用“快速确认 + 异步执行”模式: + 1. 消费者接收到消息 2. 解析出 `bankOrderId` 3. 提交任务至协程池或 Redis 队列 @@ -92,20 +107,27 @@ BusinessLogic --> |结果| SupplierQuery 该模式有效避免因业务处理耗时导致消息积压或重复消费。 -**章节来源** +**章节来源** + - [order_notify.go](file://internal/service/notify/order_notify.go#L185-L217) - [supplier_query.go](file://internal/schema/query/supplier_query.go#L89-L116) ## 队列管理器与任务处理器协作机制 -系统通过 `QueueManager` 实现对 Redis 队列的统一管理,其核心结构包含 `redisClient`、`queues` 映射、`registry` 处理器注册表、`taskFactory` 任务工厂等。 + +系统通过 `QueueManager` 实现对 Redis 队列的统一管理,其核心结构包含 `redisClient`、`queues` 映射、`registry` 处理器注册表、 +`taskFactory` 任务工厂等。 ### 队列创建与获取 + `GetOrCreateQueue` 方法根据队列名与通道 ID 生成唯一键,若队列不存在则创建新的 `RedisQueue` 实例,并注册到 `queues` 映射中。 ### 任务注册与调度 -`HandlerRegistry` 接口定义处理器注册与获取机制。`DefaultHandlerRegistry` 使用 `taskType:channelID` 作为键存储 `HandlerFunc`。`DefaultTaskHandler` 通过注册表查找对应处理器并执行。 + +`HandlerRegistry` 接口定义处理器注册与获取机制。`DefaultHandlerRegistry` 使用 `taskType:channelID` 作为键存储 +`HandlerFunc`。`DefaultTaskHandler` 通过注册表查找对应处理器并执行。 ### 任务入队流程 + `EnqueueTask` 方法首先获取或创建队列,然后调用 `RedisQueue.Enqueue` 将任务序列化后通过 `RPush` 写入 Redis 列表。 ```mermaid @@ -131,16 +153,20 @@ Handler->>Handler : 执行业务逻辑 end ``` -**图示来源** +**图示来源** + - [manager.go](file://internal/service/supplier/third_party/queue/manager.go#L104-L113) - [handlers.go](file://internal/service/supplier/third_party/queue/handlers.go#L70-L103) - [queue.go](file://internal/service/supplier/third_party/queue/queue.go#L286-L310) ## 工作协程池设计 + `WorkerPool` 是一个通用的协程池实现,用于并发执行任务。 ### 核心结构 + `WorkerPool` 包含以下关键字段: + - `workers`:协程数量 - `taskChan`:任务通道 - `results`:结果通道 @@ -148,6 +174,7 @@ end - `metrics`:性能指标 ### 任务执行流程 + `Start` 方法启动指定数量的 `worker` 协程。每个 `worker` 持续监听 `taskChan`,一旦接收到任务即调用 `task.Execute(ctx)` 执行。 ```mermaid @@ -168,22 +195,27 @@ Continue --> ListenTask end ``` -**图示来源** +**图示来源** + - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L65-L71) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L74-L89) ## 连接管理与消息确认 + 系统通过 `message.GetActiveMQConn()` 获取全局唯一的 ActiveMQ 连接实例,确保连接复用与资源节约。 -所有消费者均采用 `stomp.AckClient` 模式,即客户端手动确认。消费者在成功提交异步任务后立即调用 `conn.Ack(v)` 确认消息。若确认失败,系统会记录错误日志但不会重新入队,依赖上游重试机制保障可靠性。 +所有消费者均采用 `stomp.AckClient` 模式,即客户端手动确认。消费者在成功提交异步任务后立即调用 `conn.Ack(v)` +确认消息。若确认失败,系统会记录错误日志但不会重新入队,依赖上游重试机制保障可靠性。 该模式平衡了性能与可靠性,避免因处理失败导致消息堆积。 -**章节来源** +**章节来源** + - [order_notify.go](file://internal/service/notify/order_notify.go#L185-L217) - [send_message.go](file://internal/service/message/send_message.go#L1-L25) ## 重试策略与死信队列 + 当前系统未显式配置死信队列(DLX/DLQ),但通过多层队列机制实现软性重试: 1. **ActiveMQ 层**:消费者未确认时消息保持在队列中 @@ -193,6 +225,7 @@ end 对于订单通知,系统通过 `GetNotifyInfosNotSuccess` 查询未成功通知的记录,由定时任务重新触发,形成补偿机制。 ## 消费性能调优 + 系统通过以下方式优化消费性能: - **并发消费**:每个消费者可启动多个工作协程 @@ -204,17 +237,22 @@ end `QueueManager` 支持为不同队列配置不同工作协程数,实现精细化性能控制。 ## 事件解耦与业务流程 + 系统通过消息队列实现核心支付流程的解耦: ### 订单通知事件 -支付完成后,系统调用 `SendMessage` 向 `order_notify` 队列发送 `bankOrderId`。消费者异步调用 `SendOrderNotify` 执行回调,更新 `notify_info` 表状态。该机制避免因第三方回调超时阻塞主流程。 + +支付完成后,系统调用 `SendMessage` 向 `order_notify` 队列发送 `bankOrderId`。消费者异步调用 `SendOrderNotify` 执行回调,更新 +`notify_info` 表状态。该机制避免因第三方回调超时阻塞主流程。 ### 渠道查询事件 + 对于需要轮询结果的渠道,系统将 `bankOrderId` 发送至 `order_query` 队列。消费者创建带定时器的查询任务,实现延迟查询与自动重试。 `notify_info.go` 定义了通知记录的数据结构与数据库操作,包括插入、查询、更新等方法,是异步通知持久化的基础。 -**章节来源** +**章节来源** + - [notify_info.go](file://internal/models/notify/notify_info.go#L1-L76) - [mq_config.go](file://internal/config/mq_config.go#L1-L59) - [send_message.go](file://internal/service/message/send_message.go#L1-L25) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/数据模型/商户模型.md b/.qoder/repowiki/zh/content/数据模型/商户模型.md index 2d7c6df..99a5291 100644 --- a/.qoder/repowiki/zh/content/数据模型/商户模型.md +++ b/.qoder/repowiki/zh/content/数据模型/商户模型.md @@ -9,6 +9,7 @@ ## 目录 + 1. [引言](#引言) 2. [核心数据结构](#核心数据结构) 3. [商户状态与生命周期管理](#商户状态与生命周期管理) @@ -22,9 +23,12 @@ ## 引言 -本文档旨在深入解析`kami_gateway`项目中的商户模型,以`merchant_info.go`文件中的`MerchantInfo`结构体为核心,全面阐述商户系统的设计理念与实现细节。文档将详细解析商户的关键字段,包括状态、密钥、代理归属和支付回调配置等,阐明商户与负载信息之间的关联关系,以及这些设计如何支持多通道轮询和单通道指定等业务场景。同时,文档将结合`pay_resp.go`中`PayBaseResp`的`MerchantInfo`字段,说明商户信息在API响应中的使用方式,并涵盖商户的创建、启用/禁用、密钥轮换等管理流程。 +本文档旨在深入解析`kami_gateway`项目中的商户模型,以`merchant_info.go`文件中的`MerchantInfo` +结构体为核心,全面阐述商户系统的设计理念与实现细节。文档将详细解析商户的关键字段,包括状态、密钥、代理归属和支付回调配置等,阐明商户与负载信息之间的关联关系,以及这些设计如何支持多通道轮询和单通道指定等业务场景。同时,文档将结合 +`pay_resp.go`中`PayBaseResp`的`MerchantInfo`字段,说明商户信息在API响应中的使用方式,并涵盖商户的创建、启用/禁用、密钥轮换等管理流程。 **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) ## 核心数据结构 @@ -57,21 +61,28 @@ class MerchantInfo { ``` **Diagram sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) ## 商户状态与生命周期管理 ### 状态字段设计 + `Status`字段是`MerchantInfo`结构体中的一个关键字符串类型字段,用于标识商户的当前状态。该字段的设计意图是实现对商户生命周期的精细化管理,通过不同的状态值来控制商户在系统中的可用性。 ### 状态管理流程 -商户的生命周期管理主要通过`UpdateMerchant`函数来实现。该函数接收一个`MerchantInfo`对象作为参数,并将其更新到数据库中。通过修改`Status`字段的值(例如,从"active"改为"inactive"),可以实现商户的启用或禁用操作。此操作通常在商户管理后台的审核流程中被调用。 + +商户的生命周期管理主要通过`UpdateMerchant`函数来实现。该函数接收一个`MerchantInfo`对象作为参数,并将其更新到数据库中。通过修改 +`Status`字段的值(例如,从"active"改为"inactive"),可以实现商户的启用或禁用操作。此操作通常在商户管理后台的审核流程中被调用。 ### 创建与删除 -商户的创建由`InsertMerchantInfo`函数负责,该函数将一个新的`MerchantInfo`对象插入数据库。当需要永久移除一个商户时,则调用`DeleteMerchantByUid`函数,通过`merchant_uid`作为唯一标识进行删除。 + +商户的创建由`InsertMerchantInfo`函数负责,该函数将一个新的`MerchantInfo`对象插入数据库。当需要永久移除一个商户时,则调用 +`DeleteMerchantByUid`函数,通过`merchant_uid`作为唯一标识进行删除。 ```mermaid sequenceDiagram @@ -93,6 +104,7 @@ Service-->>Admin : 返回操作成功 ``` **Diagram sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L14-L14) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L157-L165) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L188-L197) @@ -100,6 +112,7 @@ Service-->>Admin : 返回操作成功 - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L199-L207) **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L14-L14) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L157-L165) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L188-L197) @@ -109,13 +122,20 @@ Service-->>Admin : 返回操作成功 ## 商户密钥与安全机制 ### 密钥字段设计 -`MerchantKey`和`MerchantSecret`是两个至关重要的安全字段。`MerchantKey`作为商户的公开标识,用于在API调用中识别商户身份。而`MerchantSecret`则是商户的私有密钥,用于生成和验证API请求的签名,确保通信的完整性和防篡改性。 + +`MerchantKey`和`MerchantSecret`是两个至关重要的安全字段。`MerchantKey`作为商户的公开标识,用于在API调用中识别商户身份。而 +`MerchantSecret`则是商户的私有密钥,用于生成和验证API请求的签名,确保通信的完整性和防篡改性。 ### 密钥轮换流程 -密钥轮换是保障系统安全的重要措施。当商户需要更新其密钥时,系统会调用`UpdateMerchant`函数,将新的`MerchantKey`和`MerchantSecret`值写入数据库。此操作会立即生效,旧的密钥将失效。在实际业务中,密钥轮换通常需要商户在管理后台主动触发,并可能涉及通知下游系统更新配置。 + +密钥轮换是保障系统安全的重要措施。当商户需要更新其密钥时,系统会调用`UpdateMerchant`函数,将新的`MerchantKey`和 +`MerchantSecret`值写入数据库。此操作会立即生效,旧的密钥将失效。在实际业务中,密钥轮换通常需要商户在管理后台主动触发,并可能涉及通知下游系统更新配置。 ### 密钥使用场景 -在支付回调等关键业务流程中,系统会通过`GetMerchantByUid`获取商户信息,然后使用其`MerchantSecret`来验证第三方回调请求的签名。例如,在多个第三方支付渠道(如`StarSilenceImpl`, `NinjaCardImpl`, `KuaiFuImpl`等)的`PayNotify`方法中,都包含了通过`merchant.GetMerchantByUid`获取商户信息并使用`MerchantSecret`进行验签的逻辑。 + +在支付回调等关键业务流程中,系统会通过`GetMerchantByUid`获取商户信息,然后使用其`MerchantSecret` +来验证第三方回调请求的签名。例如,在多个第三方支付渠道(如`StarSilenceImpl`, `NinjaCardImpl`, `KuaiFuImpl`等)的`PayNotify` +方法中,都包含了通过`merchant.GetMerchantByUid`获取商户信息并使用`MerchantSecret`进行验签的逻辑。 ```mermaid sequenceDiagram @@ -134,6 +154,7 @@ end ``` **Diagram sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L19-L20) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L157-L165) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L188-L197) @@ -142,6 +163,7 @@ end - [kuaifu.go](file://internal/service/supplier/third_party/kuaifu.go#L122-L183) **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L19-L20) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L157-L165) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L188-L197) @@ -149,16 +171,20 @@ end ## 代理归属与通道配置 ### 代理归属设计 + `BelongAgentUid`字段用于建立商户与代理之间的从属关系。该字段存储了代理的唯一标识符,使得系统能够清晰地追踪每个商户是由哪个代理发展而来,这对于分润计算和渠道管理至关重要。 ### 支付通道配置 + 商户模型支持两种支付通道选择策略: + - **单通道指定**:通过`SinglePayForRoadUid`和`SinglePayForRoadName`字段,商户可以被强制绑定到一个特定的支付通道。 - **多通道轮询**:通过`RollPayForRoadCode`和`RollPayForRoadName`字段,商户可以被配置为从一组通道中进行轮询或负载均衡。 这种设计提供了极大的灵活性,允许运营人员根据商户的风险等级、业务需求或通道稳定性来配置最合适的支付策略。 **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L15-L15) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L30-L31) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L32-L33) @@ -166,10 +192,14 @@ end ## 商户负载信息与多通道策略 ### 负载信息模型 -`merchant_load_info.go`文件定义了`MerchantLoadInfo`结构体,用于记录商户在各个支付通道上的负载情况。其核心字段包括`MerchantUid`(关联商户)、`RoadUid`(关联通道)和`LoadAmount`(负载金额)。 + +`merchant_load_info.go`文件定义了`MerchantLoadInfo`结构体,用于记录商户在各个支付通道上的负载情况。其核心字段包括 +`MerchantUid`(关联商户)、`RoadUid`(关联通道)和`LoadAmount`(负载金额)。 ### 业务场景支持 + `MerchantLoadInfo`与`MerchantInfo`的关联,为实现复杂的支付路由策略提供了数据基础。 + - **多通道轮询**:系统可以根据`MerchantLoadInfo`中记录的各通道负载金额,实现基于负载的轮询或加权轮询,将支付请求分配到负载较低的通道,从而实现流量的均衡分布。 - **单通道指定**:当`MerchantInfo`的`SinglePayForRoadUid`被设置时,系统会忽略负载信息,直接将所有请求路由到指定的通道,确保业务的确定性。 @@ -191,36 +221,47 @@ MerchantInfo "1" -- "0..*" MerchantLoadInfo : 通过MerchantUid关联 ``` **Diagram sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) - [merchant_load_info.go](file://internal/models/merchant/merchant_load_info.go#L12-L22) **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) - [merchant_load_info.go](file://internal/models/merchant/merchant_load_info.go#L12-L22) ## API响应中的商户信息 ### 响应结构集成 + 在`pay_resp.go`文件中,`PayBaseResp`结构体包含了一个`MerchantInfo`类型的字段。这表明,在支付相关的API响应中,商户的完整信息会被直接嵌入到响应体中返回给客户端。 ### 使用方式 + 这种设计使得客户端(如商户的前端应用)无需进行额外的API调用来获取商户信息。例如,在一个支付成功的响应中,客户端可以立即获取到商户名称、支付费率等信息,用于展示或后续处理。这提高了API的效率和用户体验。 **Section sources** + - [pay_resp.go](file://internal/schema/response/pay_resp.go#L10-L10) ## 数据库设计与约束 ### 表结构 + `MerchantInfo`结构体映射到数据库中的`merchant_info`表。该表通过`MerchantUid`字段作为业务主键,确保了商户的唯一性。 ### 唯一性约束 -虽然在提供的代码片段中未直接体现,但根据`IsExistByMerchantUid`和`IsExistByMerchantName`等查询函数的存在,可以推断数据库层面必然存在针对`merchant_uid`和`merchant_name`的唯一索引,以防止创建重复的商户。 + +虽然在提供的代码片段中未直接体现,但根据`IsExistByMerchantUid`和`IsExistByMerchantName`等查询函数的存在,可以推断数据库层面必然存在针对 +`merchant_uid`和`merchant_name`的唯一索引,以防止创建重复的商户。 ### 负载信息表 -`MerchantLoadInfo`结构体映射到`merchant_load_info`表,用于存储商户通道的负载数据。该表通过`MerchantUid`和`RoadUid`的组合来标识一条唯一的负载记录。 + +`MerchantLoadInfo`结构体映射到`merchant_load_info`表,用于存储商户通道的负载数据。该表通过`MerchantUid`和`RoadUid` +的组合来标识一条唯一的负载记录。 **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L34-L34) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L40-L42) - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L44-L46) @@ -230,22 +271,31 @@ MerchantInfo "1" -- "0..*" MerchantLoadInfo : 通过MerchantUid关联 ## 敏感信息存储策略 ### 加密处理 -`LoginPassword`字段用于存储商户后台登录的密码。根据安全最佳实践,该字段在数据库中存储的绝不是明文密码。系统在调用`InsertMerchantInfo`或`UpdateMerchant`之前,会使用`utils`包中的加密工具(如`AES_ECB.go`)对密码进行加密。在验证密码时,同样需要先对用户输入的密码进行加密后再与数据库中的密文进行比对。 + +`LoginPassword`字段用于存储商户后台登录的密码。根据安全最佳实践,该字段在数据库中存储的绝不是明文密码。系统在调用 +`InsertMerchantInfo`或`UpdateMerchant`之前,会使用`utils`包中的加密工具(如`AES_ECB.go` +)对密码进行加密。在验证密码时,同样需要先对用户输入的密码进行加密后再与数据库中的密文进行比对。 ### 安全考量 + 这种设计确保了即使数据库发生泄露,攻击者也无法直接获取到商户的登录凭证,从而保护了商户账户的安全。 **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L21-L21) - [AES_ECB.go](file://internal/utils/AES_ECB.go) ## IP白名单验证机制 ### 白名单字段 + `WhiteIps`字段是一个字符串类型,用于存储允许访问该商户API的IP地址列表。多个IP地址通常以逗号或分号分隔。 ### 验证流程 -在接收到商户的API请求时,网关服务会首先获取请求来源的IP地址,然后调用`GetMerchantByUid`获取商户信息。接着,系统会检查`WhiteIps`列表中是否包含该请求IP。如果不在白名单内,请求将被立即拒绝,返回相应的错误码。此验证逻辑通常在API网关的中间件或控制器的前置处理中实现。 + +在接收到商户的API请求时,网关服务会首先获取请求来源的IP地址,然后调用`GetMerchantByUid`获取商户信息。接着,系统会检查 +`WhiteIps`列表中是否包含该请求IP。如果不在白名单内,请求将被立即拒绝,返回相应的错误码。此验证逻辑通常在API网关的中间件或控制器的前置处理中实现。 **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L23-L23) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/数据模型/数据模型.md b/.qoder/repowiki/zh/content/数据模型/数据模型.md index a13e3f5..5510f48 100644 --- a/.qoder/repowiki/zh/content/数据模型/数据模型.md +++ b/.qoder/repowiki/zh/content/数据模型/数据模型.md @@ -12,6 +12,7 @@ ## 目录 + 1. [订单模型](#订单模型) 2. [商户模型](#商户模型) 3. [账户模型](#账户模型) @@ -21,30 +22,44 @@ ## 订单模型 -订单模型是系统的核心,由 `OrderInfo` 结构体定义,位于 `internal/models/order/order_info.go` 文件中。该模型记录了支付订单的完整信息,包括订单金额、状态、商户信息、支付通道等关键字段。 +订单模型是系统的核心,由 `OrderInfo` 结构体定义,位于 `internal/models/order/order_info.go` +文件中。该模型记录了支付订单的完整信息,包括订单金额、状态、商户信息、支付通道等关键字段。 ### 核心字段与数据类型 + `OrderInfo` 结构体包含以下主要字段: + - **主键与标识**: `Id` (int, 主键), `BankOrderId` (string, 系统订单ID), `MerchantOrderId` (string, 商户订单ID) -- **金额信息**: `OrderAmount` (float64, 提交金额), `ShowAmount` (float64, 待支付金额), `FactAmount` (float64, 实际支付金额) -- **状态与时间**: `Status` (string, 支付状态), `CreateTime` (*time.Time, 创建时间), `UpdateTime` (*time.Time, 更新时间), `PayTime` (*time.Time, 支付时间) -- **商户与代理**: `MerchantUid` (string, 商户ID), `MerchantName` (string, 商户名称), `AgentUid` (string, 代理ID), `AgentName` (string, 代理名称) -- **支付通道**: `RoadUid` (string, 通道标识), `PayProductCode` (string, 支付产品编码), `PayTypeName` (string, 支付产品名称) +- **金额信息**: `OrderAmount` (float64, 提交金额), `ShowAmount` (float64, 待支付金额), `FactAmount` (float64, + 实际支付金额) +- **状态与时间**: `Status` (string, 支付状态), `CreateTime` (*time.Time, 创建时间), `UpdateTime` (*time.Time, 更新时间), + `PayTime` (*time.Time, 支付时间) +- **商户与代理**: `MerchantUid` (string, 商户ID), `MerchantName` (string, 商户名称), `AgentUid` (string, 代理ID), + `AgentName` (string, 代理名称) +- **支付通道**: `RoadUid` (string, 通道标识), `PayProductCode` (string, 支付产品编码), `PayTypeName` (string, + 支付产品名称) - **扩展信息**: `ExValue` (string, 扩展属性,通常为JSON), `CardReturnData` (string, 卡片返回数据) ### 索引 + 根据代码中的查询方法,可以推断出以下索引的存在,以支持高效的查询: + - `bank_order_id` 字段上存在唯一索引或主键索引,用于通过 `GetOrderByBankOrderId` 方法快速查找。 - `merchant_order_id` 字段上存在索引,用于通过 `GetOrderByMerchantOrderId` 方法查找。 - `merchant_uid` 和 `road_uid` 字段上存在复合索引,用于通过 `GetByUidAndRoadUid` 方法查找。 - `status` 字段上存在索引,用于统计成功订单率等聚合操作。 ### 关联模型 + 订单模型与多个其他模型存在紧密关联: -- **订单利润信息 (`OrderProfitInfo`)**: 通过 `BankOrderId` 或 `MerchantOrderId` 与 `OrderProfitInfo` 表关联。当创建订单时,会使用 `InsertOrderAndOrderProfit` 事务方法同时插入两条记录,确保数据一致性。`HiddenOrder` 函数在处理隐藏订单时,也会同步复制利润信息。 -- **订单结算信息 (`OrderSettleInfo`)**: 当订单支付成功后,`SolvePaySuccess` 服务函数会创建一条 `OrderSettleInfo` 记录,用于标记该订单可以进行结算。两者通过 `BankOrderId` 进行关联。 + +- **订单利润信息 (`OrderProfitInfo`)**: 通过 `BankOrderId` 或 `MerchantOrderId` 与 `OrderProfitInfo` 表关联。当创建订单时,会使用 + `InsertOrderAndOrderProfit` 事务方法同时插入两条记录,确保数据一致性。`HiddenOrder` 函数在处理隐藏订单时,也会同步复制利润信息。 +- **订单结算信息 (`OrderSettleInfo`)**: 当订单支付成功后,`SolvePaySuccess` 服务函数会创建一条 `OrderSettleInfo` + 记录,用于标记该订单可以进行结算。两者通过 `BankOrderId` 进行关联。 **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L25-L68) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L92-L112) - [order_settle_info.go](file://internal/models/order/order_settle_info.go#L32-L45) @@ -55,18 +70,26 @@ 商户模型由 `MerchantInfo` 结构体定义,位于 `internal/models/merchant/merchant_info.go` 文件中,用于管理商户的基本信息和配置。 ### 核心字段与数据类型 + `MerchantInfo` 结构体包含以下主要字段: + - **主键与标识**: `Id` (int, 主键), `MerchantUid` (string, 商户唯一ID), `MerchantName` (string, 商户名称) -- **认证信息**: `LoginAccount` (string, 登录账号), `LoginPassword` (string, 登录密码), `MerchantKey` (string, 支付密钥), `MerchantSecret` (string, 支付密钥) +- **认证信息**: `LoginAccount` (string, 登录账号), `LoginPassword` (string, 登录密码), `MerchantKey` (string, 支付密钥), + `MerchantSecret` (string, 支付密钥) - **代理关系**: `BelongAgentUid` (string, 所属代理ID), `BelongAgentName` (string, 所属代理名称) - **支付配置**: `SinglePayForRoadUid` (string, 单一支付通道ID), `RollPayForRoadCode` (string, 轮询支付通道编码) - **状态与时间**: `Status` (string, 状态), `CreateTime` (time.Time, 创建时间), `UpdateTime` (time.Time, 更新时间) ### 关联模型 + 商户模型与以下模型存在关联: -- **商户加载信息 (`MerchantLoadInfo`)**: 通过 `MerchantUid` 字段关联。`MerchantLoadInfo` 记录了商户在特定支付通道上的押款信息。`MerchantAbleAmount` 服务函数在解款时会查询此信息,而 `settle` 函数在结算时会根据商户的押款配置创建新的 `MerchantLoadInfo` 记录。 + +- **商户加载信息 (`MerchantLoadInfo`)**: 通过 `MerchantUid` 字段关联。`MerchantLoadInfo` 记录了商户在特定支付通道上的押款信息。 + `MerchantAbleAmount` 服务函数在解款时会查询此信息,而 `settle` 函数在结算时会根据商户的押款配置创建新的 + `MerchantLoadInfo` 记录。 **Section sources** + - [merchant_info.go](file://internal/models/merchant/merchant_info.go#L12-L32) - [merchant_load_info.go](file://internal/models/merchant/merchant_load_info.go#L11-L20) @@ -75,17 +98,26 @@ 账户模型由 `AccountInfo` 结构体定义,位于 `internal/models/accounts/account.go` 文件中,用于管理商户账户的资金状态。 ### 核心字段与数据类型 + `AccountInfo` 结构体包含以下主要字段: + - **主键与标识**: `Id` (int, 主键), `AccountUid` (string, 账户ID), `AccountName` (string, 账户名称) -- **资金信息**: `Balance` (float64, 账户总余额), `SettleAmount` (float64, 已结算金额), `WaitAmount` (float64, 待结算资金), `FreezeAmount` (float64, 冻结金额), `LoanAmount` (float64, 押款金额), `PayforAmount` (float64, 代付在途金额) +- **资金信息**: `Balance` (float64, 账户总余额), `SettleAmount` (float64, 已结算金额), `WaitAmount` (float64, + 待结算资金), `FreezeAmount` (float64, 冻结金额), `LoanAmount` (float64, 押款金额), `PayforAmount` (float64, + 代付在途金额) - **状态与时间**: `Status` (string, 状态), `CreateTime` (time.Time, 创建时间), `UpdateTime` (time.Time, 更新时间) ### 与代理商利润的联动 -尽管 `agent_profit.go` 文件中 `AgentProfit` 结构体为空,但从 `OrderProfitInfo` 模型中可以清晰地看到其设计意图。`OrderProfitInfo` 包含了 `AgentProfit` (代理利润) 和 `AgentRate` (代理费率) 字段。这表明代理商的利润信息是通过订单利润来计算和累积的。 -当一笔订单成功结算时,`SolvePaySuccess` 服务函数会更新 `AccountInfo` 的 `Balance` 和 `WaitAmount`。同时,`OrderProfitInfo` 中计算出的 `AgentProfit` 会作为平台利润的一部分,最终体现在平台的总收益中。因此,代理商的利润并非直接存储在独立的 `AgentProfit` 表中,而是作为 `OrderProfitInfo` 的一个计算结果字段存在,并通过聚合查询来统计代理商的总利润。 +尽管 `agent_profit.go` 文件中 `AgentProfit` 结构体为空,但从 `OrderProfitInfo` 模型中可以清晰地看到其设计意图。 +`OrderProfitInfo` 包含了 `AgentProfit` (代理利润) 和 `AgentRate` (代理费率) 字段。这表明代理商的利润信息是通过订单利润来计算和累积的。 + +当一笔订单成功结算时,`SolvePaySuccess` 服务函数会更新 `AccountInfo` 的 `Balance` 和 `WaitAmount`。同时,`OrderProfitInfo` +中计算出的 `AgentProfit` 会作为平台利润的一部分,最终体现在平台的总收益中。因此,代理商的利润并非直接存储在独立的 +`AgentProfit` 表中,而是作为 `OrderProfitInfo` 的一个计算结果字段存在,并通过聚合查询来统计代理商的总利润。 **Section sources** + - [account.go](file://internal/models/accounts/account.go#L12-L26) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L12-L39) - [settle_service.go](file://internal/service/settle_service.go#L42-L141) @@ -186,6 +218,7 @@ MERCHANT_INFO }o--|| MERCHANT_INFO : "belongs_to_agent" ``` **Diagram sources** + - [order_info.go](file://internal/models/order/order_info.go#L19-L68) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L12-L39) - [order_settle_info.go](file://internal/models/order/order_settle_info.go#L12-L28) @@ -198,17 +231,23 @@ MERCHANT_INFO }o--|| MERCHANT_INFO : "belongs_to_agent" 订单的数据生命周期从创建到最终结算,经历多个状态流转。 ### 订单状态流转 -1. **创建 (Created)**: 当商户发起支付请求时,系统调用 `CreateOrderInfo` 服务函数,创建一条 `OrderInfo` 记录,初始状态为 `created`。 -2. **等待支付 (WAIT)**: 订单信息生成后,状态更新为 `wait`,等待用户完成支付。 -3. **支付成功 (SUCCESS)**: 当上游支付通道返回成功通知时,`SolvePaySuccess` 服务函数被触发。该函数执行一个数据库事务,将 `OrderInfo` 的状态更新为 `success`,同时更新 `OrderProfitInfo` 的状态,并创建一条 `OrderSettleInfo` 记录。 -4. **结算完成**: `OrderSettleInfo` 的 `is_complete_settle` 字段从 `no` 变为 `yes`,标志着该订单已完成结算。 + +1. **创建 (Created)**: 当商户发起支付请求时,系统调用 `CreateOrderInfo` 服务函数,创建一条 `OrderInfo` 记录,初始状态为 + `created`。 +2. **等待支付 (WAIT)**: 订单信息生成后,状态更新为 `wait`,等待用户完成支付。 +3. **支付成功 (SUCCESS)**: 当上游支付通道返回成功通知时,`SolvePaySuccess` 服务函数被触发。该函数执行一个数据库事务,将 + `OrderInfo` 的状态更新为 `success`,同时更新 `OrderProfitInfo` 的状态,并创建一条 `OrderSettleInfo` 记录。 +4. **结算完成**: `OrderSettleInfo` 的 `is_complete_settle` 字段从 `no` 变为 `yes`,标志着该订单已完成结算。 ### 关键业务规则 + - **数据一致性**: 在创建订单和利润信息时,必须使用 `InsertOrderAndOrderProfit` 事务方法,确保两条记录同时成功或失败。 - **幂等性**: `SolvePaySuccess` 函数在处理支付成功通知时,会先检查订单状态,防止重复处理。 -- **资金安全**: 在结算 (`settle`) 操作中,会使用 `SELECT ... FOR UPDATE` 语句锁定 `account_info` 和 `order_settle_info` 记录,防止并发操作导致的资金错误。 +- **资金安全**: 在结算 (`settle`) 操作中,会使用 `SELECT ... FOR UPDATE` 语句锁定 `account_info` 和 `order_settle_info` + 记录,防止并发操作导致的资金错误。 **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L108-L115) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L92-L112) - [settle_service.go](file://internal/service/settle_service.go#L42-L141) @@ -219,18 +258,23 @@ MERCHANT_INFO }o--|| MERCHANT_INFO : "belongs_to_agent" 系统使用 Beego ORM 进行数据库的 CRUD 操作。 ### CRUD 操作示例 + - **创建 (Create)**: 使用 `orm.NewOrm().Insert()` 方法插入单条记录。例如,`InsertOrder` 函数用于创建订单。 -- **读取 (Read)**: 使用 `QueryTable().Filter().All()` 模式进行查询。例如,`GetOrderByBankOrderId` 函数通过 `bank_order_id` 查询订单。 +- **读取 (Read)**: 使用 `QueryTable().Filter().All()` 模式进行查询。例如,`GetOrderByBankOrderId` 函数通过 `bank_order_id` + 查询订单。 - **更新 (Update)**: 使用 `QueryTable().Filter().Update()` 方法更新记录。例如,`UpdateOrderStatus` 函数用于更新订单状态。 - **删除 (Delete)**: 使用 `QueryTable().Filter().Delete()` 方法删除记录。例如,`DeleteMerchantByUid` 函数用于删除商户。 ### 查询性能优化策略 + - **索引优化**: 如上所述,对 `bank_order_id`, `merchant_order_id`, `status` 等高频查询字段建立索引。 - **分页查询**: 对于列表查询,使用 `Limit(display, offset)` 进行分页,避免一次性加载过多数据。例如,`GetOrderByMap` 函数。 - **批量操作**: 在需要处理多条记录时,使用原生 SQL 或 ORM 的批量方法,减少数据库交互次数。 -- **缓存**: 对于不经常变动的配置信息(如商户信息),可以在应用层引入 Redis 缓存,减少数据库压力。代码中的 `internal/cache` 目录表明系统已具备缓存能力。 +- **缓存**: 对于不经常变动的配置信息(如商户信息),可以在应用层引入 Redis 缓存,减少数据库压力。代码中的 `internal/cache` + 目录表明系统已具备缓存能力。 **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L108-L115) - [order_info.go](file://internal/models/order/order_info.go#L203-L217) - [order_info.go](file://internal/models/order/order_info.go#L344-L351) diff --git a/.qoder/repowiki/zh/content/数据模型/订单模型.md b/.qoder/repowiki/zh/content/数据模型/订单模型.md index d40b794..a581330 100644 --- a/.qoder/repowiki/zh/content/数据模型/订单模型.md +++ b/.qoder/repowiki/zh/content/数据模型/订单模型.md @@ -9,6 +9,7 @@ ## 目录 + 1. [简介](#简介) 2. [订单核心模型](#订单核心模型) 3. [订单状态生命周期](#订单状态生命周期) @@ -19,40 +20,48 @@ 8. [高并发数据一致性保障](#高并发数据一致性保障) ## 简介 -本文档详细阐述了支付网关系统中的订单模型设计,重点分析`OrderInfo`结构体及其相关联的利润、结算等模型。文档涵盖了订单字段定义、状态流转、数据关系、操作示例及性能优化策略,为开发人员提供全面的订单系统参考。 + +本文档详细阐述了支付网关系统中的订单模型设计,重点分析`OrderInfo` +结构体及其相关联的利润、结算等模型。文档涵盖了订单字段定义、状态流转、数据关系、操作示例及性能优化策略,为开发人员提供全面的订单系统参考。 ## 订单核心模型 `OrderInfo`结构体是订单系统的核心数据模型,定义了订单的完整信息。以下是对关键字段的详细解释: ### 基础信息字段 + - **MerchantOrderId**: 字符串类型,商户订单ID,由商户系统生成,用于商户侧订单追踪。 - **BankOrderId**: 字符串类型,本系统订单ID,作为系统内订单的唯一标识。 - **BankTransId**: 字符串类型,上游流水ID,记录上游支付通道返回的交易流水号。 ### 金额相关字段 + - **OrderAmount**: float64类型,订单提交的金额,即用户下单时的原始金额。 - **ShowAmount**: float64类型,待支付的金额,可能因优惠活动等与原始金额不同。 - **FactAmount**: float64类型,用户实际支付金额,是订单最终完成支付的金额,对账和结算以此为准。 ### 通道与路由字段 + - **RoadUid**: 字符串类型,通道标识,唯一标识一个支付通道,是路由和结算的关键字段。 - **RoadName**: 字符串类型,通道名称,用于展示和日志记录。 - **RollPoolCode**: 字符串类型,轮询池编码,标识订单所属的通道轮询池。 - **PayProductCode**: 字符串类型,上游支付公司的编码代号,用于标识支付服务提供商。 ### 状态与时间字段 + - **Status**: 字符串类型,订单支付状态,控制订单的生命周期流转。 - **CreateTime**: *time.Time类型,订单创建时间。 - **PayTime**: *time.Time类型,用户支付时间,订单成功时更新。 - **UpdateTime**: *time.Time类型,订单最后更新时间。 ### 扩展与安全字段 + - **ExValue**: 字符串类型,扩展属性,可用于存储JSON格式的额外信息。 - **IsIpRestricted**: 整型,IP限制状态标识。 - **IsReplace**: 整型,标识订单是否已被替换(如隐藏订单场景)。 **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L19-L68) ## 订单状态生命周期 @@ -60,6 +69,7 @@ 订单状态经历了从创建到最终结算的完整生命周期,各状态之间的流转逻辑如下: ### 状态流转图 + ```mermaid graph TD A[wait] --> |支付成功| B[success] @@ -72,6 +82,7 @@ E --> |退款完成| G[refunded] ``` ### 状态说明 + - **wait**: 订单创建后的初始状态,等待用户支付。 - **success**: 用户支付成功,订单完成。 - **fail**: 支付失败,可能因余额不足、密码错误等原因。 @@ -82,9 +93,12 @@ E --> |退款完成| G[refunded] - **unfreeze**: 冻结订单已解冻,恢复结算。 ### 状态变更操作 -状态变更通过`UpdateOrderStatus`函数实现,该函数确保订单状态和卡片返回数据的原子性更新。对于需要同步更新多个关联表的场景(如订单和利润表),系统使用`SwitchOrderAndOrderProfitStatus`函数在事务中完成操作,保证数据一致性。 + +状态变更通过`UpdateOrderStatus`函数实现,该函数确保订单状态和卡片返回数据的原子性更新。对于需要同步更新多个关联表的场景(如订单和利润表),系统使用 +`SwitchOrderAndOrderProfitStatus`函数在事务中完成操作,保证数据一致性。 **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L40-L40) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L120-L147) @@ -93,6 +107,7 @@ E --> |退款完成| G[refunded] 订单系统包含多个关联模型,共同构成完整的订单数据生态。 ### 实体关系图(ER图) + ```mermaid erDiagram ORDER_INFO { @@ -144,17 +159,22 @@ ORDER_PROFIT_INFO }o--|| PLATFORM_PROFIT : "一对多" ``` **Diagram sources** + - [order_info.go](file://internal/models/order/order_info.go#L19-L68) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L12-L39) - [order_settle_info.go](file://internal/models/order/order_settle_info.go#L12-L28) - [platform_profit.go](file://internal/models/order/platform_profit.go#L2-L11) ### 模型关系说明 -- **OrderInfo 与 OrderProfitInfo**: 一对一关系。`OrderInfo`存储订单基础信息,`OrderProfitInfo`存储订单的利润分润信息。两者通过`BankOrderId`关联,通常在订单创建时同时插入。 + +- **OrderInfo 与 OrderProfitInfo**: 一对一关系。`OrderInfo`存储订单基础信息,`OrderProfitInfo`存储订单的利润分润信息。两者通过 + `BankOrderId`关联,通常在订单创建时同时插入。 - **OrderInfo 与 OrderSettleInfo**: 一对一关系。`OrderSettleInfo`存储订单的结算信息,包括结算金额、是否允许结算等状态。 -- **OrderProfitInfo 与 PlatformProfit**: 一对多关系。`PlatformProfit`是聚合统计表,由多个`OrderProfitInfo`记录汇总生成,用于平台级的利润报表。 +- **OrderProfitInfo 与 PlatformProfit**: 一对多关系。`PlatformProfit`是聚合统计表,由多个`OrderProfitInfo` + 记录汇总生成,用于平台级的利润报表。 **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L19-L68) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L12-L39) - [order_settle_info.go](file://internal/models/order/order_settle_info.go#L12-L28) @@ -165,14 +185,18 @@ ORDER_PROFIT_INFO }o--|| PLATFORM_PROFIT : "一对多" 系统使用Beego ORM进行数据库操作,以下为关键操作的代码示例。 ### 订单创建 + 订单创建需保证`OrderInfo`和`OrderProfitInfo`的原子性插入,通过事务实现: + ```go // 使用InsertOrderAndOrderProfit函数 success := InsertOrderAndOrderProfit(ctx, orderInfo, orderProfitInfo) ``` ### 订单查询 + 提供多种查询方式,支持按不同条件过滤: + ```go // 按银行订单ID查询 order := GetOrderByBankOrderId(ctx, "BANK123456") @@ -189,7 +213,9 @@ orders := GetOrderByMap(ctx, params, 10, 0) ``` ### 订单更新 + 更新订单状态等关键信息: + ```go // 更新订单状态 err := UpdateOrderStatus(ctx, "BANK123456", "success", "{\"cardNo\":\"1234\"}") @@ -199,6 +225,7 @@ success := InsertPayTime(ctx, "MCH789012") ``` **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L118-L124) - [order_info.go](file://internal/models/order/order_info.go#L305-L313) - [order_info.go](file://internal/models/order/order_info.go#L344-L351) @@ -209,16 +236,19 @@ success := InsertPayTime(ctx, "MCH789012") 为保障高频查询的性能,系统对关键字段建立了数据库索引。 ### 高频查询字段 + - **MerchantOrderId**: 商户系统最常用的查询条件,必须保证唯一性和高效查询。 - **BankOrderId**: 系统内部核心标识,所有内部操作的基础查询条件。 - **Status**: 状态筛选是报表和对账的基础,查询频率极高。 ### 索引设计 + - **唯一索引**: 在`BankOrderId`和`MerchantOrderId`上建立唯一索引,防止重复订单。 - **复合索引**: 针对常见查询组合建立复合索引,例如`(merchant_uid, status, create_time)`用于商户订单列表查询。 - **状态索引**: 在`Status`字段上建立普通索引,加速状态筛选。 **Section sources** + - [order_info.go](file://internal/models/order/order_info.go#L19-L68) ## 数据归档与清理机制 @@ -226,10 +256,12 @@ success := InsertPayTime(ctx, "MCH789012") 为控制数据库规模,系统实施数据归档与清理策略。 ### 归档策略 + - **时间分区**: 订单表按月或按季度进行分区,历史数据自动归档到对应分区。 - **冷热分离**: 近期活跃数据(如3个月内)保留在主库,历史数据迁移至归档库或数据仓库。 ### 清理机制 + - **TTL策略**: 通过定时任务清理已归档且超过保留期限(如1年)的数据。 - **软删除**: 对于需要保留审计痕迹的场景,采用`IsDeleted`标记而非物理删除。 @@ -238,11 +270,14 @@ success := InsertPayTime(ctx, "MCH789012") 在高并发场景下,系统通过多种机制保障数据一致性。 ### 事务控制 + 关键操作(如创建订单、更新状态)均在数据库事务中执行,确保原子性。 ### 乐观锁与悲观锁 + - **乐观锁**: 在非关键路径使用版本号或时间戳进行乐观并发控制。 - **悲观锁**: 在资金变动等关键操作中,使用`SELECT ... FOR UPDATE`语句加行锁。 ### 分布式锁 + 对于跨服务的复杂业务流程,使用Redis实现分布式锁,防止并发冲突。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/数据模型/账户与代理商模型.md b/.qoder/repowiki/zh/content/数据模型/账户与代理商模型.md index 3c890ee..691c7f2 100644 --- a/.qoder/repowiki/zh/content/数据模型/账户与代理商模型.md +++ b/.qoder/repowiki/zh/content/数据模型/账户与代理商模型.md @@ -13,6 +13,7 @@ ## 目录 + 1. [账户模型设计](#账户模型设计) 2. [代理商模型与层级关系](#代理商模型与层级关系) 3. [账户资金字段详解](#账户资金字段详解) @@ -46,15 +47,18 @@ class AccountInfo { } ``` -**图表来源** +**图表来源** + - [account.go](file://internal/models/accounts/account.go#L12-L26) -**本节来源** +**本节来源** + - [account.go](file://internal/models/accounts/account.go#L12-L26) ## 代理商模型与层级关系 -系统通过 `AgentInfo` 结构体管理代理商信息,与商户账户形成层级管理关系。每个代理商可管理多个商户账户,通过 `AgentUid` 字段建立关联。代理商与商户之间通过 `AgentName` 和 `AgentUid` 字段在订单利润表中建立分润关系。 +系统通过 `AgentInfo` 结构体管理代理商信息,与商户账户形成层级管理关系。每个代理商可管理多个商户账户,通过 `AgentUid` +字段建立关联。代理商与商户之间通过 `AgentName` 和 `AgentUid` 字段在订单利润表中建立分润关系。 ```mermaid classDiagram @@ -85,12 +89,14 @@ AgentInfo --> OrderProfitInfo : "关联" AccountInfo --> OrderProfitInfo : "生成" ``` -**图表来源** +**图表来源** + - [agent_info.go](file://internal/models/agent/agent_info.go#L12-L27) - [account.go](file://internal/models/accounts/account.go#L12-L26) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L12-L39) -**本节来源** +**本节来源** + - [agent_info.go](file://internal/models/agent/agent_info.go#L12-L27) - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L12-L39) @@ -107,16 +113,19 @@ AccountInfo --> OrderProfitInfo : "生成" 这些字段共同构成了账户资金的完整状态机,确保资金流动的准确追踪。 -**本节来源** +**本节来源** + - [account.go](file://internal/models/accounts/account.go#L17-L22) ## 账户状态管理机制 -账户状态通过 `Status` 字段进行管理,采用字符串枚举方式表示账户的生命周期状态。系统通过 `GetAccountByUid`、`UpdateAccount` 等方法实现状态的查询和更新,所有状态变更操作均通过事务保证数据一致性。 +账户状态通过 `Status` 字段进行管理,采用字符串枚举方式表示账户的生命周期状态。系统通过 `GetAccountByUid`、`UpdateAccount` +等方法实现状态的查询和更新,所有状态变更操作均通过事务保证数据一致性。 账户状态变更遵循严格的业务流程,如结算、冻结、解冻等操作都需要经过完整的业务验证和事务处理,确保状态转换的正确性和安全性。 -**本节来源** +**本节来源** + - [account.go](file://internal/models/accounts/account.go#L14-L14) - [account.go](file://internal/models/accounts/account.go#L95-L103) @@ -142,10 +151,12 @@ class AccountHistoryInfo { } ``` -**图表来源** +**图表来源** + - [account_history_info.go](file://internal/models/accounts/account_history_info.go#L12-L25) -**本节来源** +**本节来源** + - [account_history_info.go](file://internal/models/accounts/account_history_info.go#L12-L25) ## 代理商利润计算逻辑 @@ -168,11 +179,13 @@ participant 代理商利润 订单服务-->>支付系统 : 处理完成 ``` -**图表来源** +**图表来源** + - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L36-L36) - [pay_solve.go](file://internal/service/pay_solve.go#L131-L163) -**本节来源** +**本节来源** + - [order_profit_info.go](file://internal/models/order/order_profit_info.go#L36-L36) - [pay_solve.go](file://internal/service/pay_solve.go#L131-L163) @@ -182,13 +195,15 @@ participant 代理商利润 资金流水记录包含完整的上下文信息,包括订单号、变动类型、金额、手续费、变动后余额等,确保每一笔资金流动都可追溯。所有流水记录操作都与主业务操作在同一个数据库事务中完成,保证数据一致性。 -**本节来源** +**本节来源** + - [account_history_info.go](file://internal/models/accounts/account_history_info.go#L27-L35) - [pay_solve.go](file://internal/service/pay_solve.go#L131-L163) ## 账户余额原子性操作 -账户余额更新采用数据库事务和行级锁机制确保原子性。在 `SolvePaySuccess` 方法中,通过 `SELECT ... FOR UPDATE` 语句获取账户记录的排他锁,防止并发场景下的超卖问题。 +账户余额更新采用数据库事务和行级锁机制确保原子性。在 `SolvePaySuccess` 方法中,通过 `SELECT ... FOR UPDATE` +语句获取账户记录的排他锁,防止并发场景下的超卖问题。 所有余额更新操作都在事务中完成,包括账户余额更新、待结算资金更新、生成资金流水记录等,确保操作的原子性和一致性。系统还通过余额校验机制防止负余额的出现。 @@ -203,15 +218,18 @@ F --> G[提交事务] E --> H[返回错误] ``` -**图表来源** +**图表来源** + - [pay_solve.go](file://internal/service/pay_solve.go#L131-L163) -**本节来源** +**本节来源** + - [pay_solve.go](file://internal/service/pay_solve.go#L131-L163) ## 账户安全机制 账户安全通过多层机制保障: + - **密码存储**: 登录密码和支付密码均采用加密存储,防止明文泄露 - **并发控制**: 通过数据库事务和行级锁防止并发操作导致的数据不一致 - **操作审计**: 所有资金操作都记录到历史表,便于审计和追溯 @@ -219,13 +237,15 @@ E --> H[返回错误] 安全机制贯穿于账户操作的各个环节,从数据存储到业务处理都考虑了安全性要求。 -**本节来源** +**本节来源** + - [agent_info.go](file://internal/models/agent/agent_info.go#L13-L14) - [pay_solve.go](file://internal/service/pay_solve.go#L131-L163) ## 代理商分润定时结算 -代理商分润结算由 `OrderSettle` 定时任务处理,通过 `settle_service.go` 中的 `OrderSettleInit` 方法启动。系统每隔2分钟检查待结算订单,自动完成结算流程。 +代理商分润结算由 `OrderSettle` 定时任务处理,通过 `settle_service.go` 中的 `OrderSettleInit` +方法启动。系统每隔2分钟检查待结算订单,自动完成结算流程。 结算流程包括:更新订单结算状态、调整账户资金、处理押款逻辑等。对于需要押款的商户,系统还会根据配置的押款天数自动释放押款金额,整个过程完全自动化,确保代理商利润的及时分配。 @@ -245,8 +265,10 @@ J --> K[继续检查] B --> |无订单| L[等待下次执行] ``` -**图表来源** +**图表来源** + - [settle_service.go](file://internal/service/settle_service.go#L63-L122) -**本节来源** +**本节来源** + - [settle_service.go](file://internal/service/settle_service.go#L12-L236) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/核心架构/任务调度架构.md b/.qoder/repowiki/zh/content/核心架构/任务调度架构.md index 4fe8ab0..3ba74d0 100644 --- a/.qoder/repowiki/zh/content/核心架构/任务调度架构.md +++ b/.qoder/repowiki/zh/content/核心架构/任务调度架构.md @@ -15,6 +15,7 @@ ## 目录 + 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) @@ -26,9 +27,11 @@ 9. [结论](#结论) ## 简介 + 本文档详细解析了任务调度系统中third_party/pool目录下的订单池与任务队列机制。重点阐述了OrderPoolService接口如何通过workerPool、eventBus和taskPool实现高并发下的订单处理能力。文档详细描述了NewOrderPoolService初始化过程中的资源配置策略,包括工作协程池、Redis事件总线和GoPool连接池的配置。结合event_handlers.go中的事件处理器注册逻辑,阐明了系统如何通过发布-订阅模式响应订单提交、状态变更等事件。分析了task.go中任务执行流程与order.go定时任务的协同机制,并解释了getAllRoadUids等关键方法在路由选择中的作用。最后提供了workerCount调优、Redis连接复用和事件广播延迟控制等性能优化建议。 ## 项目结构 + 任务调度系统的核心功能集中在third_party/pool目录下,该目录实现了订单池与任务队列的核心机制。系统通过模块化设计,将订单处理、事件管理、任务执行等职责分离,形成了清晰的组件结构。 ```mermaid @@ -74,24 +77,29 @@ EventHandler --> OrderQueryHandler ``` **图表来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L26-L52) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L15-L25) - [event.go](file://internal/service/supplier/third_party/pool/event.go#L60-L66) - [task.go](file://internal/service/supplier/third_party/pool/task.go#L15-L25) **本节来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L1-L585) - [project_structure](file://#L1-L200) ## 核心组件 + 订单池服务的核心组件包括OrderPoolService接口、OrderPoolServiceImpl实现类、WorkerPool工作协程池、EventBus事件总线和TaskPool任务池。这些组件协同工作,实现了高并发下的订单处理能力。 **本节来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L26-L52) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L15-L25) - [event.go](file://internal/service/supplier/third_party/pool/event.go#L60-L66) ## 架构概述 + 任务调度系统采用发布-订阅模式和工作协程池架构,实现了高效的订单处理流程。系统通过Redis作为消息队列和状态存储,结合Go协程池技术,实现了高并发、低延迟的订单处理能力。 ```mermaid @@ -128,13 +136,16 @@ end ``` **图表来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L55-L73) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L36-L46) - [event.go](file://internal/service/supplier/third_party/pool/event.go#L80-L88) - [task.go](file://internal/service/supplier/third_party/pool/task.go#L15-L25) ## 详细组件分析 + ### OrderPoolService接口分析 + OrderPoolService接口定义了订单池服务的核心功能,包括服务的启动与停止、订单的推送与提交、以及订单ID的查询。该接口通过清晰的方法定义,为订单处理提供了标准化的操作接口。 ```mermaid @@ -178,12 +189,15 @@ OrderPoolService <|-- OrderPoolServiceImpl ``` **图表来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L26-L52) **本节来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L26-L52) ### 初始化过程分析 + NewOrderPoolService函数是订单池服务的初始化入口,负责创建和配置所有核心组件。该函数通过依赖注入的方式,将配置、Redis客户端等外部依赖注入到服务实现中,并初始化工作协程池、事件总线和任务池等核心组件。 ```mermaid @@ -200,6 +214,7 @@ ReturnService --> End([初始化完成]) ``` **图表来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L55-L73) - [metrics.go](file://internal/service/supplier/third_party/pool/metrics.go#L50-L85) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L36-L46) @@ -207,9 +222,11 @@ ReturnService --> End([初始化完成]) - [card_sender/enums.go](file://internal/service/supplier/third_party/pool/card_sender/enums.go#L49-L72) **本节来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L55-L73) ### 事件处理机制分析 + 系统通过事件总线(EventBus)实现了发布-订阅模式,将订单处理的各个阶段解耦。事件处理器负责监听特定类型的事件,并执行相应的业务逻辑,如订单创建、处理完成、查询等。 ```mermaid @@ -261,16 +278,19 @@ RedisEventBus --> EventHandler : "处理" ``` **图表来源** + - [event.go](file://internal/service/supplier/third_party/pool/event.go#L60-L66) - [event_handlers.go](file://internal/service/supplier/third_party/pool/event_handlers.go#L15-L25) - [events.go](file://internal/service/supplier/third_party/pool/events.go#L15-L25) **本节来源** + - [event.go](file://internal/service/supplier/third_party/pool/event.go#L60-L177) - [event_handlers.go](file://internal/service/supplier/third_party/pool/event_handlers.go#L15-L182) - [events.go](file://internal/service/supplier/third_party/pool/events.go#L15-L136) ### 任务执行流程分析 + 任务执行流程是订单处理的核心,包括订单匹配、补充和刷新等操作。系统通过工作协程池并行处理这些任务,确保了高并发下的处理效率。 ```mermaid @@ -295,14 +315,17 @@ Note over OrderPoolService,WorkerPool : 订单补充流程 ``` **图表来源** + - [task.go](file://internal/service/supplier/third_party/pool/task.go#L15-L165) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L15-L90) **本节来源** + - [task.go](file://internal/service/supplier/third_party/pool/task.go#L15-L165) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L15-L90) ## 依赖分析 + 系统各组件之间的依赖关系清晰,通过接口定义和依赖注入实现了松耦合。核心依赖包括配置管理、Redis客户端、工作协程池、事件总线和任务池。 ```mermaid @@ -336,6 +359,7 @@ OrderFailedHandler --> OrderPoolServiceImpl ``` **图表来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L40-L52) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L15-L25) - [event.go](file://internal/service/supplier/third_party/pool/event.go#L60-L66) @@ -343,12 +367,15 @@ OrderFailedHandler --> OrderPoolServiceImpl - [event_handlers.go](file://internal/service/supplier/third_party/pool/event_handlers.go#L15-L25) **本节来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L40-L52) - [worker.go](file://internal/service/supplier/third_party/pool/worker.go#L15-L25) - [event.go](file://internal/service/supplier/third_party/pool/event.go#L60-L66) ## 性能考虑 + ### workerCount调优 + workerCount参数决定了工作协程池的大小,直接影响系统的并发处理能力。建议根据系统负载和硬件资源进行调优: - **低负载环境**:设置为10-20,避免资源浪费 @@ -358,6 +385,7 @@ workerCount参数决定了工作协程池的大小,直接影响系统的并发 监控指标`worker_pool_size`可以帮助评估当前配置的合理性,如果该指标经常达到上限,说明需要增加workerCount。 ### Redis连接复用 + 系统通过Redis客户端实现了连接复用,减少了连接创建和销毁的开销。建议: - 保持长连接,避免频繁创建和销毁连接 @@ -365,6 +393,7 @@ workerCount参数决定了工作协程池的大小,直接影响系统的并发 - 监控连接使用情况,及时发现连接泄漏 ### 事件广播延迟控制 + 事件广播的延迟直接影响系统的响应速度。通过以下方式可以优化延迟: - 调整事件处理协程池大小(pool字段) @@ -372,7 +401,9 @@ workerCount参数决定了工作协程池的大小,直接影响系统的并发 - 监控事件处理时间,及时发现性能瓶颈 ## 故障排除指南 + ### 订单处理失败 + 当订单处理失败时,系统会记录相关错误并尝试重试。排查步骤: 1. 检查`order_pool_failed_total`监控指标 @@ -381,6 +412,7 @@ workerCount参数决定了工作协程池的大小,直接影响系统的并发 4. 验证发卡任务类型的实现是否正确 ### 事件处理器未响应 + 如果事件处理器未按预期工作,检查: 1. 事件是否正确发布到事件总线 @@ -389,6 +421,7 @@ workerCount参数决定了工作协程池的大小,直接影响系统的并发 4. 事件处理器的实现是否存在错误 ### 订单池大小异常 + 当订单池大小异常时: 1. 检查`order_pool_size`监控指标 @@ -397,9 +430,11 @@ workerCount参数决定了工作协程池的大小,直接影响系统的并发 4. 查看是否有大量过期订单未被清理 **本节来源** + - [service.go](file://internal/service/supplier/third_party/pool/service.go#L300-L333) - [task.go](file://internal/service/supplier/third_party/pool/task.go#L15-L165) - [metrics.go](file://internal/service/supplier/third_party/pool/metrics.go#L50-L85) ## 结论 + 任务调度系统通过精心设计的架构和组件,实现了高效、可靠的订单处理能力。系统采用发布-订阅模式和工作协程池架构,结合Redis作为消息队列和状态存储,能够处理高并发的订单请求。通过合理的资源配置和性能优化,系统能够在保证低延迟的同时,处理大量的订单任务。建议在实际部署中根据具体负载情况进行参数调优,并持续监控系统性能指标,确保系统的稳定运行。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/核心架构/供应商集成架构.md b/.qoder/repowiki/zh/content/核心架构/供应商集成架构.md index bdfd9a5..4158894 100644 --- a/.qoder/repowiki/zh/content/核心架构/供应商集成架构.md +++ b/.qoder/repowiki/zh/content/核心架构/供应商集成架构.md @@ -11,6 +11,7 @@ ## 目录 + 1. [接口定义与统一标准](#接口定义与统一标准) 2. [适配器实现与继承关系](#适配器实现与继承关系) 3. [核心方法实现分析](#核心方法实现分析) @@ -52,9 +53,11 @@ class ScanData { ``` **Diagram sources** + - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L26-L36) **Section sources** + - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L1-L37) ### 接口方法说明 @@ -73,7 +76,8 @@ class ScanData { ## 适配器实现与继承关系 -各供应商通过实现 `PayInterface` 接口来接入系统,同时继承 `web.Controller` 以获得Web请求处理能力。这种设计模式遵循了适配器模式,将不同供应商的特定实现适配到统一的接口标准上。 +各供应商通过实现 `PayInterface` 接口来接入系统,同时继承 `web.Controller` +以获得Web请求处理能力。这种设计模式遵循了适配器模式,将不同供应商的特定实现适配到统一的接口标准上。 ```mermaid classDiagram @@ -143,12 +147,14 @@ WalMartImpl ..|> PayInterface ``` **Diagram sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L39-L41) - [jd.go](file://internal/service/supplier/third_party/jd.go#L36-L38) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L33-L35) - [walmart.go](file://internal/service/supplier/third_party/walmart.go#L35-L37) **Section sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L1-L482) - [jd.go](file://internal/service/supplier/third_party/jd.go#L1-L434) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L1-L448) @@ -189,12 +195,14 @@ ReturnSuccess --> End ``` **Diagram sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L118-L149) - [jd.go](file://internal/service/supplier/third_party/jd.go#L114-L145) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L132-L165) - [walmart.go](file://internal/service/supplier/third_party/walmart.go#L188-L219) **Section sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L118-L149) - [jd.go](file://internal/service/supplier/third_party/jd.go#L114-L145) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L132-L165) @@ -244,12 +252,14 @@ WriteSuccess --> End ``` **Diagram sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L168-L260) - [jd.go](file://internal/service/supplier/third_party/jd.go#L165-L212) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L167-L223) - [walmart.go](file://internal/service/supplier/third_party/walmart.go#L233-L260) **Section sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L168-L260) - [jd.go](file://internal/service/supplier/third_party/jd.go#L165-L212) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L167-L223) @@ -287,12 +297,14 @@ ReturnFalse --> End ``` **Diagram sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L262-L323) - [jd.go](file://internal/service/supplier/third_party/jd.go#L214-L275) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L225-L287) - [walmart.go](file://internal/service/supplier/third_party/walmart.go#L262-L322) **Section sources** + - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L262-L323) - [jd.go](file://internal/service/supplier/third_party/jd.go#L214-L275) - [t_mall_game.go](file://internal/service/supplier/third_party/t_mall_game.go#L225-L287) @@ -333,9 +345,11 @@ registerSupplier ..> PayInterface : "持有" ``` **Diagram sources** + - [init.go](file://internal/service/supplier/third_party/init.go#L151-L153) **Section sources** + - [init.go](file://internal/service/supplier/third_party/init.go#L1-L197) ### 注册机制 diff --git a/.qoder/repowiki/zh/content/核心架构/支付服务架构.md b/.qoder/repowiki/zh/content/核心架构/支付服务架构.md index a0e26e0..e3d3519 100644 --- a/.qoder/repowiki/zh/content/核心架构/支付服务架构.md +++ b/.qoder/repowiki/zh/content/核心架构/支付服务架构.md @@ -9,6 +9,7 @@ ## 目录 + 1. [简介](#简介) 2. [核心组件](#核心组件) 3. [支付请求处理流程](#支付请求处理流程) @@ -19,17 +20,22 @@ 8. [幂等性保障](#幂等性保障) ## 简介 -本文档详细阐述了支付服务的架构设计,重点分析了支付请求从扫码控制器进入系统后的完整处理流程。文档聚焦于`pay_service.go`和`pay_solve.go`的实现机制,涵盖了订单创建、状态管理、金额校验和结果回调等核心环节。 + +本文档详细阐述了支付服务的架构设计,重点分析了支付请求从扫码控制器进入系统后的完整处理流程。文档聚焦于`pay_service.go`和 +`pay_solve.go`的实现机制,涵盖了订单创建、状态管理、金额校验和结果回调等核心环节。 **Section sources** + - [pay_service.go](file://internal/service/pay_service.go#L1-L50) - [pay_solve.go](file://internal/service/pay_solve.go#L1-L50) ## 核心组件 -支付服务的核心组件包括扫码控制器(`scan_controller.go`)、支付服务(`pay_service.go`)、支付解决方案(`pay_solve.go`)以及订单信息模型(`order_info.go`)。这些组件协同工作,实现了完整的支付处理流程。 +支付服务的核心组件包括扫码控制器(`scan_controller.go`)、支付服务(`pay_service.go`)、支付解决方案(`pay_solve.go`) +以及订单信息模型(`order_info.go`)。这些组件协同工作,实现了完整的支付处理流程。 **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L1-L50) - [pay_service.go](file://internal/service/pay_service.go#L1-L50) - [pay_solve.go](file://internal/service/pay_solve.go#L1-L50) @@ -61,12 +67,14 @@ ScanController->>Client : 返回支付结果 ``` **Diagram sources ** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L69-L316) - [pay_service.go](file://internal/service/pay_service.go#L305-L359) - [pay_solve.go](file://internal/service/pay_solve.go#L37-L195) - [order_info.go](file://internal/models/order/order_info.go#L370-L376) **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L69-L316) - [pay_service.go](file://internal/service/pay_service.go#L305-L359) @@ -91,14 +99,17 @@ UpdateRoad --> End([结束]) ``` **Diagram sources ** + - [pay_solve.go](file://internal/service/pay_solve.go#L37-L195) **Section sources** + - [pay_solve.go](file://internal/service/pay_solve.go#L37-L195) ## 金额不一致处理逻辑 -当实际支付金额与订单金额不一致时,系统通过`SolvePaySuccessByAmountDifferent`函数处理此情况。该函数首先检查通道是否允许金额不一致的重发,然后根据重发次数决定是否继续处理。 +当实际支付金额与订单金额不一致时,系统通过`SolvePaySuccessByAmountDifferent` +函数处理此情况。该函数首先检查通道是否允许金额不一致的重发,然后根据重发次数决定是否继续处理。 ```mermaid flowchart TD @@ -117,9 +128,11 @@ CallScan --> End([结束]) ``` **Diagram sources ** + - [pay_solve.go](file://internal/service/supplier/third_party/init.go#L173-L195) **Section sources** + - [pay_solve.go](file://internal/service/supplier/third_party/init.go#L173-L195) ## 数据交互模式 @@ -157,12 +170,14 @@ PayService --> OrderInfo : "数据操作" ``` **Diagram sources ** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L69-L316) - [pay_service.go](file://internal/service/pay_service.go#L305-L359) - [pay_solve.go](file://internal/service/pay_solve.go#L37-L195) - [order_info.go](file://internal/models/order/order_info.go#L370-L376) **Section sources** + - [scan_controller.go](file://internal/controllers/scan_controller.go#L69-L316) - [pay_service.go](file://internal/service/pay_service.go#L305-L359) - [pay_solve.go](file://internal/service/pay_solve.go#L37-L195) @@ -173,6 +188,7 @@ PayService --> OrderInfo : "数据操作" 系统实现了完善的异常处理机制,通过`SolvePayFail`函数处理支付失败的情况。该函数会更新订单状态为失败,并记录失败原因。同时,系统使用异步任务池处理回调通知,避免阻塞主流程。 **Section sources** + - [pay_solve.go](file://internal/service/pay_solve.go#L198-L254) ## 幂等性保障 @@ -180,4 +196,5 @@ PayService --> OrderInfo : "数据操作" 为了确保操作的幂等性,系统在关键操作上采用了数据库事务和状态检查机制。例如,在处理支付成功时,会先检查订单是否已经是成功状态,避免重复处理。 **Section sources** + - [pay_solve.go](file://internal/service/pay_solve.go#L37-L195) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/核心架构/核心架构.md b/.qoder/repowiki/zh/content/核心架构/核心架构.md index a56225c..f269b2c 100644 --- a/.qoder/repowiki/zh/content/核心架构/核心架构.md +++ b/.qoder/repowiki/zh/content/核心架构/核心架构.md @@ -15,6 +15,7 @@ ## 目录 + 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) @@ -26,10 +27,14 @@ 9. [结论](#结论) ## 简介 + 本文档旨在深入分析支付服务(payfor_service.go)和支付解决方案(payfor_solve.go)的实现,解释它们如何协同工作来处理支付请求。文档详细描述了供应商接口(supplier_interface.go)的设计模式,这是一个关键的扩展点,允许系统集成多种第三方支付渠道(如Apple、京东卡、沃尔玛)。同时,文档说明了系统如何通过实现此接口来添加新的支付供应商,并涵盖订单池和任务队列的处理机制。 ## 项目结构 -本项目采用分层架构设计,主要分为配置、部署、内部服务和模型等目录。核心业务逻辑位于`internal`目录下,包括缓存、配置、常量、控制器、数据传输对象(DTO)、模型、OpenTelemetry追踪、代理、路由、模式、服务、Swagger文档、任务和工具等子模块。支付相关的核心逻辑集中在`internal/service/pay_for`和`internal/service/supplier`目录中。 + +本项目采用分层架构设计,主要分为配置、部署、内部服务和模型等目录。核心业务逻辑位于`internal` +目录下,包括缓存、配置、常量、控制器、数据传输对象(DTO)、模型、OpenTelemetry追踪、代理、路由、模式、服务、Swagger文档、任务和工具等子模块。支付相关的核心逻辑集中在 +`internal/service/pay_for`和`internal/service/supplier`目录中。 ```mermaid graph TD @@ -61,7 +66,8 @@ PayForService --> MerchantInfo PayForService --> RoadInfo ``` -**图源** +**图源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go) @@ -73,20 +79,24 @@ PayForService --> RoadInfo - [merchant_info.go](file://internal/models/merchant/merchant_info.go) - [account.go](file://internal/models/accounts/account.go) -**本节来源** +**本节来源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go) ## 核心组件 + 支付服务(payfor_service.go)负责处理支付请求的入口逻辑,包括签名验证、金额检查、订单重复性检查和支付通道选择。支付解决方案(payfor_solve.go)则负责处理支付结果的更新,包括支付成功和支付失败的处理。供应商接口(supplier_interface.go)定义了所有第三方支付供应商必须实现的方法,确保了系统的可扩展性和一致性。 -**本节来源** +**本节来源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go#L1-L330) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go#L1-L144) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L1-L37) ## 架构概述 + 系统采用接口驱动的设计模式,通过定义清晰的接口来解耦核心业务逻辑和第三方支付供应商的实现。这种设计模式带来了显著的可维护性和可扩展性优势。当需要添加新的支付供应商时,只需实现供应商接口并注册到系统中,而无需修改核心业务逻辑。 ```mermaid @@ -102,7 +112,8 @@ PayForSolve --> Database[(数据库)] PayForService --> Database ``` -**图源** +**图源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go) @@ -110,10 +121,13 @@ PayForService --> Database - [jd.go](file://internal/service/supplier/third_party/jd.go) ## 详细组件分析 + ### 支付服务分析 + 支付服务组件负责处理支付请求的完整生命周期,从接收请求到最终的支付结果查询。它首先验证请求的签名和参数,然后检查订单的重复性,最后选择合适的支付通道并发起支付请求。 #### 支付服务类图 + ```mermaid classDiagram class PayForService { @@ -149,15 +163,18 @@ SupplierInterface <|-- AppleImpl : "实现" SupplierInterface <|-- WalmartImpl : "实现" ``` -**图源** +**图源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go#L1-L330) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go#L1-L144) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L1-L37) ### 供应商接口分析 + 供应商接口是系统的关键扩展点,它定义了所有第三方支付供应商必须实现的方法。通过这种接口驱动的设计,系统可以轻松集成新的支付渠道,而无需修改核心业务逻辑。 #### 供应商接口序列图 + ```mermaid sequenceDiagram participant Client as "客户端" @@ -175,19 +192,22 @@ Supplier-->>PayForService : 返回支付结果 PayForService-->>Client : 返回支付响应 ``` -**图源** +**图源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go#L1-L330) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L1-L37) - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L1-L481) - [jd.go](file://internal/service/supplier/third_party/jd.go#L1-L433) -**本节来源** +**本节来源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go#L1-L330) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L1-L37) - [aibo.go](file://internal/service/supplier/third_party/aibo.go#L1-L481) - [jd.go](file://internal/service/supplier/third_party/jd.go#L1-L433) ## 依赖分析 + 系统通过清晰的依赖关系实现了高内聚低耦合的设计。支付服务依赖于支付解决方案和供应商接口,而具体的供应商实现则依赖于供应商接口。数据模型层为所有服务提供数据支持,确保了数据的一致性和完整性。 ```mermaid @@ -207,7 +227,8 @@ SupplierInterface --> Walmart PayforInfo --> Account ``` -**图源** +**图源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go) @@ -218,20 +239,25 @@ PayforInfo --> Account - [road_info.go](file://internal/models/road/road_info.go) - [account.go](file://internal/models/accounts/account.go) -**本节来源** +**本节来源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go) - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go) ## 性能考虑 + 系统在设计时充分考虑了性能因素。通过使用数据库事务确保数据一致性,采用缓存机制减少数据库访问,以及使用异步处理提高响应速度。此外,系统还实现了支付通道的轮询机制,确保在高并发场景下的稳定性和可靠性。 ## 故障排除指南 + 当支付请求失败时,首先检查请求的签名是否正确,然后验证支付金额是否符合要求。如果问题仍然存在,检查订单是否重复,以及支付通道是否可用。对于第三方支付供应商的问题,需要检查供应商的API文档和状态码说明。 -**本节来源** +**本节来源** + - [payfor_service.go](file://internal/service/pay_for/payfor_service.go#L1-L330) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go#L1-L144) ## 结论 + 本文档详细分析了支付服务和支付解决方案的实现,以及供应商接口的设计模式。通过接口驱动的设计,系统实现了高度的可扩展性和可维护性。未来可以进一步优化支付通道的选择算法,提高支付成功率,并增强系统的监控和告警能力。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/监控与故障排除.md b/.qoder/repowiki/zh/content/监控与故障排除.md index c42ef0d..e0982f6 100644 --- a/.qoder/repowiki/zh/content/监控与故障排除.md +++ b/.qoder/repowiki/zh/content/监控与故障排除.md @@ -18,6 +18,7 @@ ## 目录 + 1. [分布式追踪](#分布式追踪) 2. [日志诊断](#日志诊断) 3. [关键指标与Prometheus集成](#关键指标与prometheus集成) @@ -27,9 +28,11 @@ ## 分布式追踪 -本系统使用OpenTelemetry(otelTrace包)实现分布式追踪,通过`otelTrace.InitTracer()`函数初始化追踪器,配置了生产环境优化的Trace导出器、资源标识、采样策略和批量处理器。追踪器使用gRPC协议将数据发送到指定的收集器,支持gzip压缩以减少网络传输量。 +本系统使用OpenTelemetry(otelTrace包)实现分布式追踪,通过`otelTrace.InitTracer()` +函数初始化追踪器,配置了生产环境优化的Trace导出器、资源标识、采样策略和批量处理器。追踪器使用gRPC协议将数据发送到指定的收集器,支持gzip压缩以减少网络传输量。 -系统通过`otelTrace.Middleware`中间件实现请求级别的追踪。该中间件在请求处理开始时创建一个Span,从请求头中提取上游的trace context,并注入到当前context中。Span记录了HTTP方法、URL、状态码、响应大小、处理时长等关键性能指标。当请求处理时间超过5秒时,会自动标记为慢请求并记录警告日志。 +系统通过`otelTrace.Middleware`中间件实现请求级别的追踪。该中间件在请求处理开始时创建一个Span,从请求头中提取上游的trace +context,并注入到当前context中。Span记录了HTTP方法、URL、状态码、响应大小、处理时长等关键性能指标。当请求处理时间超过5秒时,会自动标记为慢请求并记录警告日志。 ```mermaid sequenceDiagram @@ -47,10 +50,12 @@ Exporter->>Collector : 发送追踪数据 ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [middleware.go](file://internal/otelTrace/middleware.go#L21-L140) **Section sources** + - [init.go](file://internal/otelTrace/init.go#L1-L257) - [middleware.go](file://internal/otelTrace/middleware.go#L1-L142) @@ -58,7 +63,8 @@ Exporter->>Collector : 发送追踪数据 系统使用`otelTrace.Logger`进行日志记录,该Logger集成了OpenTelemetry的日志导出功能。日志信息不仅会输出到标准输出,还会通过OTLP协议发送到日志收集器,实现日志的集中管理和分析。 -`otelTrace.logs.go`文件定义了`CustomLogger`结构体,它包装了Zap日志库,并提供了`WithContext`方法,可以将OpenTelemetry的context与日志记录关联起来。这使得在查看日志时,可以轻松地关联到相应的追踪信息,实现日志与追踪的联动分析。 +`otelTrace.logs.go`文件定义了`CustomLogger`结构体,它包装了Zap日志库,并提供了`WithContext` +方法,可以将OpenTelemetry的context与日志记录关联起来。这使得在查看日志时,可以轻松地关联到相应的追踪信息,实现日志与追踪的联动分析。 ```mermaid classDiagram @@ -73,18 +79,22 @@ Logger --> CustomLogger : "全局实例" ``` **Diagram sources** + - [logs.go](file://internal/otelTrace/logs.go#L1-L29) - [init.go](file://internal/otelTrace/init.go#L249-L256) **Section sources** + - [logs.go](file://internal/otelTrace/logs.go#L1-L29) - [init.go](file://internal/otelTrace/init.go#L249-L256) ## 关键指标与Prometheus集成 -系统通过`otelTrace.InitTracer()`函数配置了Metrics导出器,将关键指标通过OTLP协议发送到收集器。同时,`internal/service/supplier/third_party/pool/metrics.go`文件定义了`Metrics`结构体,用于监控订单处理相关的指标。 +系统通过`otelTrace.InitTracer()`函数配置了Metrics导出器,将关键指标通过OTLP协议发送到收集器。同时, +`internal/service/supplier/third_party/pool/metrics.go`文件定义了`Metrics`结构体,用于监控订单处理相关的指标。 这些指标包括: + - `order_pool_processed_total`: 已处理的订单总数 - `order_pool_failed_total`: 处理失败的订单总数 - `order_pool_processing_seconds`: 订单处理时间分布 @@ -111,10 +121,12 @@ I --> J[监控面板] ``` **Diagram sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [metrics.go](file://internal/service/supplier/third_party/pool/metrics.go#L1-L163) **Section sources** + - [init.go](file://internal/otelTrace/init.go#L29-L205) - [metrics.go](file://internal/service/supplier/third_party/pool/metrics.go#L1-L163) @@ -145,6 +157,7 @@ I --> J[监控面板] 3. 检查`CurrentChannelConcurrency`、`CurrentRoadConcurrency`和`CurrentFaceValueConcurrency`指标,查看当前并发数。 **Section sources** + - [order_controller.go](file://internal/controllers/order_controller.go#L1-L226) - [payfor_solve.go](file://internal/service/pay_for/payfor_solve.go#L1-L144) - [pay_service.go](file://internal/service/pay_service.go#L1-L448) @@ -156,12 +169,14 @@ I --> J[监控面板] 对于慢查询的识别,系统在`otelTrace.Middleware`中设置了5秒的阈值。当请求处理时间超过5秒时,会自动记录警告日志,并标记为慢请求。开发者可以通过分析这些日志,定位性能瓶颈。 优化建议: + 1. 优化数据库查询,添加必要的索引。 2. 使用缓存减少数据库访问。 3. 优化上游供应商接口调用,减少网络延迟。 4. 调整订单池大小和队列长度,平衡性能和资源使用。 **Section sources** + - [middleware.go](file://internal/otelTrace/middleware.go#L21-L140) - [metrics.go](file://internal/service/supplier/third_party/pool/metrics.go#L1-L163) @@ -170,11 +185,13 @@ I --> J[监控面板] 系统通过`otelTrace.monitorExporterHealth`函数实现了导出器健康状态的监控。该函数每30秒检查一次导出失败次数,如果失败次数超过10次,会记录警告日志。 告警规则建议: + 1. 当`exportFailures`超过10次时,发送告警通知。 2. 当`order_query_failed_total`在5分钟内增加超过100次时,发送告警通知。 3. 当`order_pool_processing_seconds`的95分位数超过5秒时,发送告警通知。 4. 当`order_pool_size`接近最大值时,发送告警通知。 **Section sources** + - [utils.go](file://internal/otelTrace/utils.go#L58-L60) - [metrics.go](file://internal/service/supplier/third_party/pool/metrics.go#L1-L163) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/第三方支付渠道集成.md b/.qoder/repowiki/zh/content/第三方支付渠道集成.md index ec363e5..048f9eb 100644 --- a/.qoder/repowiki/zh/content/第三方支付渠道集成.md +++ b/.qoder/repowiki/zh/content/第三方支付渠道集成.md @@ -11,6 +11,7 @@ ## 目录 + 1. [介绍](#介绍) 2. [核心接口定义](#核心接口定义) 3. [核心方法实现分析](#核心方法实现分析) @@ -23,9 +24,11 @@ 10. [常见陷阱与最佳实践](#常见陷阱与最佳实践) ## 介绍 + 本文档旨在为开发者提供一份详细的第三方支付渠道集成指南。通过分析现有支付供应商(如Apple、京东)的实现,指导开发者如何创建新的支付供应商集成。文档涵盖了从接口实现、HTTP通信、错误处理到系统注册的完整流程。 ## 核心接口定义 + 所有第三方支付供应商必须实现`PayInterface`接口,该接口定义了支付系统所需的核心功能。 ```mermaid @@ -57,13 +60,17 @@ class ScanData { ``` **图示来源** + - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L26-L36) **本节来源** + - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L1-L37) ## 核心方法实现分析 + ### Scan方法实现 + `Scan`方法是支付流程的起点,负责处理扫码支付请求。通过对比Apple和京东的实现,可以发现通用的处理模式。 ```mermaid @@ -82,14 +89,17 @@ Scan-->>开发者 : 返回支付结果 ``` **图示来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L152-L183) - [jd.go](file://internal/service/supplier/third_party/jd.go#L114-L145) **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L152-L183) - [jd.go](file://internal/service/supplier/third_party/jd.go#L114-L145) ### PayNotify方法实现 + `PayNotify`方法处理来自第三方供应商的支付回调通知,是确保交易状态同步的关键。 ```mermaid @@ -108,14 +118,17 @@ PayNotify-->>供应商 : 返回确认响应 ``` **图示来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L202-L240) - [jd.go](file://internal/service/supplier/third_party/jd.go#L165-L212) **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L202-L240) - [jd.go](file://internal/service/supplier/third_party/jd.go#L165-L212) ### PayQuery方法实现 + `PayQuery`方法用于查询订单状态,确保交易的最终一致性。 ```mermaid @@ -132,15 +145,19 @@ PayQuery-->>系统 : 返回查询结果 ``` **图示来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L242-L305) - [jd.go](file://internal/service/supplier/third_party/jd.go#L214-L275) **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L242-L305) - [jd.go](file://internal/service/supplier/third_party/jd.go#L214-L275) ## HTTP请求与响应处理 + ### 请求构建与发送 + 支付供应商通过HTTP请求与第三方系统通信,使用`httplib`库进行请求构建和发送。 ```mermaid @@ -156,14 +173,17 @@ Start([开始]) --> 构建参数["构建请求参数"] ``` **图示来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) - [jd.go](file://internal/service/supplier/third_party/jd.go#L53-L112) **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) - [jd.go](file://internal/service/supplier/third_party/jd.go#L53-L112) ### 响应解析与处理 + 收到响应后,系统需要解析JSON数据并根据业务逻辑进行处理。 ```mermaid @@ -177,11 +197,14 @@ flowchart TD ``` **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) - [jd.go](file://internal/service/supplier/third_party/jd.go#L53-L112) ## 错误处理与重试机制 + ### 错误处理策略 + 系统采用分层的错误处理策略,确保异常情况下的稳定性。 ```mermaid @@ -200,17 +223,22 @@ flowchart TD ``` **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) - [jd.go](file://internal/service/supplier/third_party/jd.go#L53-L112) ### 重试机制实现 + 通过`req.Retries(3)`设置重试次数,确保网络不稳定时的请求可靠性。 **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) ## 供应商认证机制 + ### 签名生成 + 供应商通过特定算法生成签名,确保请求的完整性和安全性。 ```mermaid @@ -222,11 +250,14 @@ flowchart TD ``` **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) - [jd.go](file://internal/service/supplier/third_party/jd.go#L53-L112) ## API限流与数据格式 + ### 限流处理 + 系统通过配置和超时设置来应对API限流。 ```mermaid @@ -239,18 +270,23 @@ flowchart TD ``` **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) - [jd.go](file://internal/service/supplier/third_party/jd.go#L53-L112) ### 数据格式规范 + 所有请求和响应都遵循统一的JSON格式规范。 **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L77-L150) - [jd.go](file://internal/service/supplier/third_party/jd.go#L53-L112) ## 新供应商集成步骤 + ### 创建供应商结构体 + 创建新的供应商实现结构体,继承必要的控制器。 ```mermaid @@ -261,31 +297,40 @@ flowchart TD ``` **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L14-L16) - [jd.go](file://internal/service/supplier/third_party/jd.go#L14-L16) ### 实现核心方法 + 按照接口定义实现所有必需的方法。 **本节来源** + - [supplier_interface.go](file://internal/service/supplier/supplier_interface.go#L26-L36) ### 添加到系统 + 将新的供应商实现文件添加到third_party目录,并在系统中注册。 **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go) - [jd.go](file://internal/service/supplier/third_party/jd.go) ## 单元测试编写 + 参考现有的`*_test.go`文件编写单元测试,确保代码质量。 **本节来源** + - [apple_test.go](file://internal/service/supplier/third_party/apple_test.go) - [jd_test.go](file://internal/service/supplier/third_party/jd_test.go) ## 常见陷阱与最佳实践 + ### 交易幂等性保证 + 通过订单号和状态检查确保交易的幂等性。 ```mermaid @@ -300,10 +345,12 @@ flowchart TD ``` **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go#L202-L240) - [jd.go](file://internal/service/supplier/third_party/jd.go#L165-L212) ### 最佳实践总结 + 1. 始终记录详细的日志信息 2. 实现完整的错误处理 3. 遵循统一的代码风格 @@ -311,5 +358,6 @@ flowchart TD 5. 确保交易的幂等性 **本节来源** + - [apple.go](file://internal/service/supplier/third_party/apple.go) - [jd.go](file://internal/service/supplier/third_party/jd.go) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/部署与配置/Docker部署指南.md b/.qoder/repowiki/zh/content/部署与配置/Docker部署指南.md index 9cdc2c3..bac328b 100644 --- a/.qoder/repowiki/zh/content/部署与配置/Docker部署指南.md +++ b/.qoder/repowiki/zh/content/部署与配置/Docker部署指南.md @@ -10,6 +10,7 @@ ## 目录 + 1. [多阶段构建详解](#多阶段构建详解) 2. [Docker Compose配置解析](#docker-compose配置解析) 3. [本地部署步骤](#本地部署步骤) @@ -28,7 +29,8 @@ - `CGO_ENABLED=0`:禁用CGO以生成静态二进制文件 - `GOOS=linux` 和 `GOARCH=amd64`:指定目标操作系统和架构 -构建过程首先将整个项目代码复制到工作目录`/build`,然后执行`go mod tidy`清理依赖并使用`go build`命令生成经过优化的静态二进制文件`main`(使用`-ldflags="-s -w"`去除调试信息以减小体积)。 +构建过程首先将整个项目代码复制到工作目录`/build`,然后执行`go mod tidy`清理依赖并使用`go build`命令生成经过优化的静态二进制文件 +`main`(使用`-ldflags="-s -w"`去除调试信息以减小体积)。 ### 运行阶段(Runtime Stage) @@ -36,17 +38,19 @@ 1. **环境变量设置**:配置了时区`TZ=Asia/Shanghai`及多个服务相关的环境变量 2. **系统配置**: - - 配置阿里云Alpine镜像源以加速包下载 - - 安装`tzdata`和`curl`等必要工具 - - 设置中国时区 + - 配置阿里云Alpine镜像源以加速包下载 + - 安装`tzdata`和`curl`等必要工具 + - 设置中国时区 3. **证书配置**: - - 安装标准CA证书包 - - 添加Comodo AAA证书以支持特定HTTPS连接 - - 更新证书信任链 + - 安装标准CA证书包 + - 添加Comodo AAA证书以支持特定HTTPS连接 + - 更新证书信任链 -最后,从构建阶段复制编译好的二进制文件`main`、配置文件目录`conf/`和数据目录`data/`到运行环境,并设置容器启动命令为`./main`,暴露端口12309。 +最后,从构建阶段复制编译好的二进制文件`main`、配置文件目录`conf/`和数据目录`data/`到运行环境,并设置容器启动命令为`./main` +,暴露端口12309。 **Section sources** + - [Dockerfile](file://deploy/Dockerfile#L1-L43) ## Docker Compose配置解析 @@ -57,25 +61,27 @@ - **构建配置**:指定构建上下文为项目根目录(`..`),使用`./deploy/Dockerfile`作为Dockerfile - **容器配置**: - - 容器名称:`kami_gateway` - - 镜像标签:`kami_gateway:$VERSION`(支持版本变量) - - 重启策略:`always`(确保容器异常退出后自动重启) + - 容器名称:`kami_gateway` + - 镜像标签:`kami_gateway:$VERSION`(支持版本变量) + - 重启策略:`always`(确保容器异常退出后自动重启) - **网络配置**:连接到外部网络`1panel-network`,实现与其他服务的通信 - **端口映射**: - - `127.0.0.1:22309:12309`:主服务端口,仅限本地访问 - - `127.0.0.1:22390:12390`:监控服务端口,仅限本地访问 + - `127.0.0.1:22309:12309`:主服务端口,仅限本地访问 + - `127.0.0.1:22390:12390`:监控服务端口,仅限本地访问 - **卷挂载**: - - 配置目录:`/data/kami/gateway/conf/` → `/app/conf/` - - 日志目录:`/data/kami/gateway/logs/` → `/app/logs/` + - 配置目录:`/data/kami/gateway/conf/` → `/app/conf/` + - 日志目录:`/data/kami/gateway/logs/` → `/app/logs/` ### 本地开发配置 `docker-compose-local.yaml`提供了简化的本地开发配置,主要差异包括: + - 使用固定标签`latest` - 端口映射为`12309:12309`,允许外部访问 - 简化的服务名称`gateway_kami` **Section sources** + - [docker-compose.yaml](file://deploy/docker-compose.yaml#L1-L23) - [docker-compose-local.yaml](file://deploy/docker-compose-local.yaml#L1-L17) @@ -91,6 +97,7 @@ cd kami_gateway ### 2. 准备配置文件 确保`conf/app.conf`中的配置正确,特别是数据库、Redis和MQ连接信息。根据需要修改以下关键配置: + - `httpport = 12309`:服务监听端口 - 数据库连接参数 - Redis连接参数 @@ -123,6 +130,7 @@ curl http://127.0.0.1:22309/health ``` **Section sources** + - [app.conf](file://conf/app.conf#L1-L77) - [main.go](file://main.go#L23-L57) @@ -133,11 +141,14 @@ curl http://127.0.0.1:22309/health **症状**:容器无法启动,日志显示"port is already allocated" **解决方案**: + 1. 检查端口占用情况: + ```bash netstat -tlnp | grep :22309 lsof -i :22309 ``` + 2. 修改`docker-compose.yaml`中的主机端口映射,例如改为`127.0.0.1:32309:12309` 3. 重启服务 @@ -146,11 +157,14 @@ lsof -i :22309 **症状**:`go mod tidy`或`go build`命令失败 **解决方案**: + 1. 确保网络连接正常,特别是对`goproxy.cn`的访问 2. 清理Go模块缓存: + ```bash go clean -modcache ``` + 3. 检查`go.mod`文件完整性 4. 确保Docker有足够的内存资源 @@ -159,10 +173,13 @@ go clean -modcache **症状**:容器启动后立即退出 **排查步骤**: + 1. 查看详细日志: + ```bash docker logs kami_gateway ``` + 2. 检查配置文件挂载是否正确 3. 验证数据库、Redis等依赖服务是否正常运行 4. 检查文件权限,确保容器内进程有足够权限访问挂载目录 @@ -172,10 +189,12 @@ docker logs kami_gateway **症状**:HTTPS连接失败,证书验证错误 **解决方案**: + 1. 确认`Dockerfile`中证书安装步骤执行成功 2. 检查`update-ca-certificates`命令输出 3. 如需添加自定义证书,可将证书文件挂载到容器并手动添加 **Section sources** + - [Dockerfile](file://deploy/Dockerfile#L1-L43) - [docker-compose.yaml](file://deploy/docker-compose.yaml#L1-L23) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/部署与配置/环境变量管理.md b/.qoder/repowiki/zh/content/部署与配置/环境变量管理.md index 5a662a1..eed41ff 100644 --- a/.qoder/repowiki/zh/content/部署与配置/环境变量管理.md +++ b/.qoder/repowiki/zh/content/部署与配置/环境变量管理.md @@ -11,6 +11,7 @@ ## 目录 + 1. [简介](#简介) 2. [预设环境变量](#预设环境变量) 3. [环境变量覆盖机制](#环境变量覆盖机制) @@ -20,13 +21,17 @@ 7. [总结](#总结) ## 简介 -`kami_gateway` 项目通过环境变量实现灵活的运行时配置,支持开发、测试和生产等多环境部署。本项目利用 Docker 和 docker-compose 提供了完整的容器化部署方案,并通过环境变量机制实现配置的动态注入与覆盖。环境变量不仅用于服务地址配置,还涉及代理服务、认证信息等关键参数,是系统可配置性的核心组成部分。 + +`kami_gateway` 项目通过环境变量实现灵活的运行时配置,支持开发、测试和生产等多环境部署。本项目利用 Docker 和 docker-compose +提供了完整的容器化部署方案,并通过环境变量机制实现配置的动态注入与覆盖。环境变量不仅用于服务地址配置,还涉及代理服务、认证信息等关键参数,是系统可配置性的核心组成部分。 **Section sources** + - [Dockerfile](file://deploy/Dockerfile#L1-L44) - [docker-compose.yaml](file://deploy/docker-compose.yaml#L1-L24) ## 预设环境变量 + 在 `Dockerfile` 中通过 `ENV` 指令预设了一系列环境变量,这些变量为系统提供了默认配置: - `serverName`: 服务器名称,默认值为"默认" @@ -42,31 +47,38 @@ 这些环境变量在容器构建时被设置,为应用提供了基础的运行配置。 **Section sources** + - [Dockerfile](file://deploy/Dockerfile#L10-L19) ## 环境变量覆盖机制 + `kami_gateway` 支持通过多种方式覆盖 Dockerfile 中预设的环境变量,实现不同环境的灵活配置。 在 `docker-compose.yaml` 文件中,虽然没有显式定义 `environment` 字段来覆盖环境变量,但通过外部卷挂载机制实现了配置的外部化: + ```yaml volumes: - /data/kami/gateway/conf/:/app/conf/ - /data/kami/gateway/logs/:/app/logs/ ``` + 这种设计允许通过挂载外部配置文件来间接影响环境变量的行为。 而在 `docker-compose-local.yaml` 中,通过简化配置实现了本地开发环境的快速部署,保留了构建上下文但简化了网络和端口配置。 运行时可以通过 `docker run` 命令的 `-e` 参数或在 `docker-compose.yml` 的 `environment` 字段中直接覆盖这些变量,例如: + ```bash docker run -e serverName="开发环境" -e gatewayAddr="http://dev.gateway:12309" kami_gateway ``` **Section sources** + - [docker-compose.yaml](file://deploy/docker-compose.yaml#L1-L24) - [docker-compose-local.yaml](file://deploy/docker-compose-local.yaml#L1-L18) ## 构建脚本与版本控制 + `build.sh` 脚本定义了项目的构建过程,其中包含了与环境变量相关的构建参数: ```bash @@ -74,11 +86,13 @@ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go ``` 虽然该脚本本身不直接处理环境变量,但在 `docker-compose.yaml` 中使用了 `$VERSION` 环境变量来控制镜像标签: + ```yaml image: kami_gateway:$VERSION ``` 这种设计允许在构建时通过传递不同的 `VERSION` 值来生成不同标签的镜像,实现版本控制。例如,可以通过以下命令构建特定版本的镜像: + ```bash VERSION=v1.2.0 docker-compose build ``` @@ -86,25 +100,33 @@ VERSION=v1.2.0 docker-compose build 这使得 CI/CD 流程能够根据 Git 标签或构建号自动创建相应版本的镜像,提高了部署的可追溯性和一致性。 **Section sources** + - [build.sh](file://build.sh#L1-L2) - [docker-compose.yaml](file://deploy/docker-compose.yaml#L6-L7) ## 实际应用案例 + 环境变量在 `kami_gateway` 中有多种实际应用场景。 ### 动态数据库配置 + 虽然数据库连接信息主要在 `app.conf` 中定义,但可以通过环境变量实现动态配置。例如,可以修改配置读取逻辑,从环境变量中获取数据库连接参数: + ```go dbhost := os.Getenv("MYSQL_HOST") dbport := os.Getenv("MYSQL_PORT") ``` + 这样可以在不同环境中使用不同的数据库实例,而无需修改配置文件。 ### 代理服务切换 + 通过 `proxyUrl`、`proxyAuthKey` 和 `proxyAuthPwd` 环境变量,可以轻松切换不同的代理服务提供商。在开发环境中可以使用测试代理,在生产环境中切换到付费的高稳定性代理服务。 ### 多环境部署 + 通过组合使用不同的环境变量,可以实现一套代码在多个环境中的部署: + - 开发环境:`serverName="开发"`,`gatewayAddr="http://localhost:12309"` - 测试环境:`serverName="测试"`,`gatewayAddr="http://test.gateway:12309"` - 生产环境:`serverName="生产"`,`gatewayAddr="https://api.gateway.com"` @@ -112,21 +134,29 @@ dbport := os.Getenv("MYSQL_PORT") 这种机制确保了配置的灵活性和安全性,敏感信息可以通过环境变量而非配置文件进行管理。 **Section sources** + - [app.conf](file://conf/app.conf#L1-L78) - [Dockerfile](file://deploy/Dockerfile#L10-L19) ## 环境变量与配置文件优先级 + 在 `kami_gateway` 中,环境变量与 `app.conf` 配置文件之间存在明确的优先级关系。 -根据 `internal/config/config.go` 中的配置读取逻辑,系统使用 beego 框架的 `web.AppConfig.String()` 方法读取配置值。beego 框架默认支持环境变量覆盖配置文件中的值,即当同名环境变量存在时,会优先使用环境变量的值。 +根据 `internal/config/config.go` 中的配置读取逻辑,系统使用 beego 框架的 `web.AppConfig.String()` 方法读取配置值。beego +框架默认支持环境变量覆盖配置文件中的值,即当同名环境变量存在时,会优先使用环境变量的值。 -例如,`app.conf` 中定义了 `httpport = 12309`,但可以通过设置 `httpport` 环境变量来覆盖此值。这种设计模式使得关键配置既可以在配置文件中提供默认值,又可以通过环境变量在部署时进行灵活调整。 +例如,`app.conf` 中定义了 `httpport = 12309`,但可以通过设置 `httpport` +环境变量来覆盖此值。这种设计模式使得关键配置既可以在配置文件中提供默认值,又可以通过环境变量在部署时进行灵活调整。 -对于 `shop::key` 这样的配置项,`GetMerchantKey()` 函数直接从配置中读取,这意味着可以通过环境变量 `shop__key`(beego 将双下划线转换为配置节分隔符)来覆盖商户密钥,增强了配置的安全性。 +对于 `shop::key` 这样的配置项,`GetMerchantKey()` 函数直接从配置中读取,这意味着可以通过环境变量 `shop__key`(beego +将双下划线转换为配置节分隔符)来覆盖商户密钥,增强了配置的安全性。 **Section sources** + - [app.conf](file://conf/app.conf#L1-L78) - [config.go](file://internal/config/config.go#L1-L45) ## 总结 -`kami_gateway` 项目通过精心设计的环境变量机制,实现了高度灵活的配置管理。从 Dockerfile 中的预设变量,到 docker-compose 的部署配置,再到运行时的动态覆盖,形成了完整的配置管理体系。这种设计不仅支持多环境部署,还提高了系统的可维护性和安全性。通过将敏感信息和环境特定配置从代码中分离,项目能够更好地适应不同的部署场景,同时保持代码库的整洁和一致性。 \ No newline at end of file + +`kami_gateway` 项目通过精心设计的环境变量机制,实现了高度灵活的配置管理。从 Dockerfile 中的预设变量,到 docker-compose +的部署配置,再到运行时的动态覆盖,形成了完整的配置管理体系。这种设计不仅支持多环境部署,还提高了系统的可维护性和安全性。通过将敏感信息和环境特定配置从代码中分离,项目能够更好地适应不同的部署场景,同时保持代码库的整洁和一致性。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/部署与配置/部署与配置.md b/.qoder/repowiki/zh/content/部署与配置/部署与配置.md index 48d037e..e03e90f 100644 --- a/.qoder/repowiki/zh/content/部署与配置/部署与配置.md +++ b/.qoder/repowiki/zh/content/部署与配置/部署与配置.md @@ -15,6 +15,7 @@ ## 目录 + 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) @@ -26,9 +27,11 @@ 9. [结论](#结论) ## 简介 + 本文档提供基于Docker和Docker Compose的完整部署与配置指南,涵盖本地开发和生产环境的设置。文档详细说明如何通过环境变量覆盖配置文件中的默认值,并提供部署后的验证步骤。 ## 项目结构 + 项目采用分层结构,主要包含配置、部署脚本、内部业务逻辑和主程序入口。部署相关文件集中于`deploy`目录,配置文件位于`conf`目录。 ```mermaid @@ -53,23 +56,28 @@ appConf --> main buildScript --> main ``` -**图示来源** +**图示来源** + - [Dockerfile](file://deploy/Dockerfile#L1-L44) - [docker-compose.yaml](file://deploy/docker-compose.yaml#L1-L24) - [app.conf](file://conf/app.conf#L1-L78) -**本节来源** +**本节来源** + - [deploy](file://deploy) - [conf](file://conf) ## 核心组件 + 核心组件包括配置管理、代理池、消息队列和数据库连接。系统通过`main.go`初始化各项服务,包括代理池、缓存、消息消费者和队列系统。 -**本节来源** +**本节来源** + - [main.go](file://main.go#L1-L59) - [config.go](file://internal/config/config.go#L1-L45) ## 架构概述 + 系统采用微服务架构,通过Beego框架提供HTTP服务,使用Redis作为缓存,MySQL作为持久化存储,ActiveMQ作为消息队列。代理池用于外部请求的负载均衡。 ```mermaid @@ -83,16 +91,19 @@ ProxyPool --> ExternalAPI[外部API] Gateway --> Backend[后端服务] ``` -**图示来源** +**图示来源** + - [main.go](file://main.go#L1-L59) - [cfg_model.go](file://internal/config/cfg_model.go#L1-L141) ## 详细组件分析 ### 配置管理分析 + 系统配置通过`app.conf`文件和环境变量双重管理,环境变量优先级高于配置文件。 #### 配置类图 + ```mermaid classDiagram class Config { @@ -129,15 +140,18 @@ Config --> ProxyInfo : "包含" MQConfig --> Config : "依赖" ``` -**图示来源** +**图示来源** + - [cfg_model.go](file://internal/config/cfg_model.go#L1-L141) - [proxy.go](file://internal/config/proxy.go#L1-L18) - [mq_config.go](file://internal/config/mq_config.go#L1-L60) ### 代理池分析 + 代理池在系统启动时初始化,支持通过环境变量动态配置代理服务器列表。 #### 代理池初始化流程图 + ```mermaid flowchart TD Start([程序启动]) --> InitProxyPool["proxy.InitProxyPool()"] @@ -152,15 +166,18 @@ Initialize --> ReturnSuccess["返回nil"] EmptyList --> Initialize ``` -**图示来源** +**图示来源** + - [main.go](file://main.go#L1-L59) - [proxy.go](file://internal/config/proxy.go#L1-L18) - [mq_config.go](file://internal/config/mq_config.go#L1-L60) ### 消息队列分析 + 系统使用消息队列处理订单查询和通知,通过独立的goroutine消费消息。 #### 消息处理序列图 + ```mermaid sequenceDiagram participant Main as "main()" @@ -176,10 +193,12 @@ Main->>third_party : StartOrderPool() Note over Notify,Queue : 启动消息消费者和队列系统 ``` -**图示来源** +**图示来源** + - [main.go](file://main.go#L1-L59) ## 依赖分析 + 系统依赖Go模块、Docker环境和外部服务。通过`go.mod`管理Go依赖,通过Docker容器化部署。 ```mermaid @@ -192,22 +211,28 @@ B --> F[其他Beego组件] C --> G[MySQL协议] ``` -**图示来源** +**图示来源** + - [Dockerfile](file://deploy/Dockerfile#L1-L44) - [go.mod](file://go.mod#L1-L20) -**本节来源** +**本节来源** + - [Dockerfile](file://deploy/Dockerfile#L1-L44) ## 性能考虑 + 系统通过缓存、代理池和消息队列提高性能。Redis缓存减少数据库访问,代理池实现请求负载均衡,消息队列解耦业务逻辑。 ## 故障排除指南 + 常见问题包括数据库连接失败、Redis连接失败和代理池初始化失败。检查相应的配置项和网络连接。 -**本节来源** +**本节来源** + - [main.go](file://main.go#L1-L59) - [cache/redis.go](file://internal/cache/redis.go#L18-L28) ## 结论 + 本文档提供了完整的部署和配置指南,涵盖了从构建到运行的全过程。通过合理的配置管理和组件设计,系统具有良好的可维护性和扩展性。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/部署与配置/配置文件详解.md b/.qoder/repowiki/zh/content/部署与配置/配置文件详解.md index bce5281..51353f7 100644 --- a/.qoder/repowiki/zh/content/部署与配置/配置文件详解.md +++ b/.qoder/repowiki/zh/content/部署与配置/配置文件详解.md @@ -10,6 +10,7 @@ ## 目录 + 1. [应用配置](#应用配置) 2. [HTTP端口配置](#http端口配置) 3. [日志配置](#日志配置) @@ -34,6 +35,7 @@ runmode = prod - `runmode`:设置运行模式为`prod`(生产环境),系统根据此模式加载相应的配置和行为 **Section sources** + - [app.conf](file://conf/app.conf#L1-L2) ## HTTP端口配置 @@ -54,6 +56,7 @@ HTTPAddr = 0.0.0.0 这些配置共同定义了应用的网络访问入口,客户端通过`http://<服务器IP>:12309`访问服务。 **Section sources** + - [app.conf](file://conf/app.conf#L2-L6) ## 日志配置 @@ -74,6 +77,7 @@ maxdays=10 - `maxdays`:日志文件最大保存天数为10天,超过此期限的日志将被自动清理 日志级别0-7分别对应: + - 0: emergency (紧急) - 1: alert (警报) - 2: critical (严重) @@ -84,6 +88,7 @@ maxdays=10 - 7: debug (调试) **Section sources** + - [app.conf](file://conf/app.conf#L9-L15) ## 数据库配置 @@ -110,6 +115,7 @@ debug = true 这些配置用于建立与MySQL数据库的连接,支持系统数据的持久化存储。 **Section sources** + - [app.conf](file://conf/app.conf#L17-L24) ## Redis配置 @@ -130,6 +136,7 @@ password = "" Redis主要用于缓存频繁访问的数据,提高系统性能和响应速度。 **Section sources** + - [app.conf](file://conf/app.conf#L26-L30) ## 消息队列配置 @@ -148,6 +155,7 @@ port = 61613 消息队列用于实现系统组件间的异步通信,提高系统的可扩展性和可靠性。 **Section sources** + - [app.conf](file://conf/app.conf#L32-L35) ## 第三方服务API配置 @@ -155,6 +163,7 @@ port = 61613 配置文件中包含了多个第三方服务的API端点和回调地址配置。 ### MF服务配置 + ```ini [mf] submit_card_url = http://test.shop.center.mf178.cn/userapi/card/submit_card @@ -162,6 +171,7 @@ query_card_url = http://test.shop.center.mf178.cn/userapi/card/order_info ``` ### Apple卡服务配置 + ```ini [appleCard] submit_card_url = http://kami_backend:12401/api/cardInfo/appleCard/submit @@ -170,6 +180,7 @@ notify_url = http://kami_gateway:12309/appleCard/notify ``` ### 京东卡服务配置 + ```ini [jdCard] submit_card_url = http://kami_backend:12401/api/cardInfo/jdCard/submit @@ -178,6 +189,7 @@ notify_url = http://kami_gateway:12309/jdCard/notify ``` ### 其他服务配置 + ```ini [tMallGame] submit_card_url=http://test.shop.center.mf178.cn/recharge/tMallGame/order/submit @@ -186,11 +198,13 @@ query_card_url=http://test.shop.center.mf178.cn/userapi/card/order_info ``` 这些配置定义了与各个第三方服务交互的API端点,包括: + - `submit_card_url`:提交卡密的接口地址 - `query_card_url`:查询卡密状态的接口地址 - `notify_url`:接收第三方服务回调通知的地址 **Section sources** + - [app.conf](file://conf/app.conf#L37-L77) ## 代理配置 @@ -207,6 +221,7 @@ proxies = [] 代理配置与环境变量`proxyUrl`协同工作,用于获取动态代理IP,实现请求的IP轮换,避免被目标网站封禁。 **Section sources** + - [app.conf](file://conf/app.conf#L77-L78) ## 环境变量与配置文件的协同 @@ -227,6 +242,7 @@ func GetProxyInfo() ProxyInfo { - `proxyAuthKey`和`proxyAuthPwd`:代理认证密钥和密码,同样优先从环境变量获取 这种设计实现了配置的灵活性: + 1. 生产环境中通过环境变量设置敏感信息,避免硬编码在配置文件中 2. 开发环境中使用默认值,简化配置 3. 可以根据不同环境动态调整代理服务 @@ -249,16 +265,19 @@ J --> K[请求完成] ``` **Diagram sources** + - [proxy.go](file://internal/config/proxy.go#L10-L17) - [proxy_pool.go](file://internal/utils/proxy_pool.go#L108-L120) **Section sources** + - [proxy.go](file://internal/config/proxy.go#L10-L17) - [proxy_pool.go](file://internal/utils/proxy_pool.go#L108-L120) ## 生产与测试环境对比 ### 生产环境配置特点 + ```ini runmode = prod dbpasswd = Woaizixkie!123 @@ -271,6 +290,7 @@ proxyUrl = https://secure.proxy.enterprise.com/api - 日志级别可能调整为较低级别(如3-4),减少日志量 ### 测试环境配置特点 + ```ini runmode = dev dbpasswd = test123 @@ -284,15 +304,16 @@ proxyUrl = https://test.proxy.service.com/api ### 配置项对系统行为的影响 -| 配置项 | 影响范围 | 生产环境建议 | 测试环境建议 | -|--------|--------|------------|------------| -| `runmode` | 系统行为模式 | prod | dev | -| `level` | 日志详细程度 | 3-4 (error-warning) | 7 (debug) | -| `maxdays` | 存储空间占用 | 30-90天 | 7-14天 | -| `debug` | 性能与安全性 | false | true | -| `proxyUrl` | 请求IP轮换 | 高质量代理服务 | 测试代理服务 | +| 配置项 | 影响范围 | 生产环境建议 | 测试环境建议 | +|------------|--------|---------------------|-----------| +| `runmode` | 系统行为模式 | prod | dev | +| `level` | 日志详细程度 | 3-4 (error-warning) | 7 (debug) | +| `maxdays` | 存储空间占用 | 30-90天 | 7-14天 | +| `debug` | 性能与安全性 | false | true | +| `proxyUrl` | 请求IP轮换 | 高质量代理服务 | 测试代理服务 | 通过合理配置这些参数,可以确保系统在不同环境中以最优方式运行,既保证生产环境的稳定性和安全性,又满足测试环境的调试需求。 **Section sources** + - [app.conf](file://conf/app.conf#L1-L78) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/项目概述.md b/.qoder/repowiki/zh/content/项目概述.md index 37f7180..d33828f 100644 --- a/.qoder/repowiki/zh/content/项目概述.md +++ b/.qoder/repowiki/zh/content/项目概述.md @@ -15,6 +15,7 @@ ## 目录 + 1. [项目简介](#项目简介) 2. [项目结构](#项目结构) 3. [核心功能](#核心功能) @@ -25,41 +26,52 @@ 8. [高级特性](#高级特性) ## 项目简介 -kami_gateway 是一个基于 Go 语言和 Beego 框架构建的高性能支付网关系统。该项目旨在为各种支付方式(包括礼品卡和其他支付渠道)提供支付处理、订单管理和供应商集成服务。系统采用 MVC 模式进行架构设计,具有良好的可扩展性和可维护性。 + +kami_gateway 是一个基于 Go 语言和 Beego 框架构建的高性能支付网关系统。该项目旨在为各种支付方式(包括礼品卡和其他支付渠道)提供支付处理、订单管理和供应商集成服务。系统采用 +MVC 模式进行架构设计,具有良好的可扩展性和可维护性。 **Section sources** + - [CLAUDE.md](file://CLAUDE.md#L1-L20) ## 项目结构 + 项目采用分层架构,主要分为以下几个目录: + - `conf`: 配置文件目录 - `deploy`: 部署相关文件 - `internal`: 核心业务逻辑 - - `controllers`: HTTP 请求处理器 - - `models`: 数据模型和数据库操作 - - `service`: 业务逻辑层 - - `dto`: 数据传输对象 - - `routers`: 路由配置 - - `config`: 配置管理 - - `cache`: 缓存管理 - - `otelTrace`: 分布式追踪 - - `utils`: 工具函数 + - `controllers`: HTTP 请求处理器 + - `models`: 数据模型和数据库操作 + - `service`: 业务逻辑层 + - `dto`: 数据传输对象 + - `routers`: 路由配置 + - `config`: 配置管理 + - `cache`: 缓存管理 + - `otelTrace`: 分布式追踪 + - `utils`: 工具函数 **Section sources** + - [main.go](file://main.go#L1-L57) ## 核心功能 + kami_gateway 提供了以下核心功能: + 1. **多渠道支付处理**: 支持多种支付渠道的集成和处理 2. **订单调度**: 实现订单的创建、查询和状态管理 3. **代付请求**: 处理代付相关的业务逻辑 4. **回调通知**: 实现订单状态变更的回调通知机制 **Section sources** + - [CLAUDE.md](file://CLAUDE.md#L50-L70) ## 系统架构 + 系统采用 MVC 模式,各层之间的关系如下: + - **控制器层 (Controllers)**: 负责处理 HTTP 请求,调用服务层进行业务处理 - **服务层 (Service)**: 实现核心业务逻辑,协调模型层进行数据操作 - **模型层 (Models)**: 负责与数据库交互,提供数据访问接口 @@ -74,11 +86,14 @@ C --> F[第三方供应商] ``` **Diagram sources** + - [internal/controllers/base_controller.go](file://internal/controllers/base_controller.go#L6-L8) - [internal/models/init.go](file://internal/models/init.go#L0-L42) ## 技术栈 + kami_gateway 采用了以下技术栈: + - **Beego v2**: Web 框架,提供 MVC 模式支持 - **OpenTelemetry**: 分布式追踪,用于监控系统性能和调试 - **Redis**: 缓存和会话管理,提高系统响应速度 @@ -88,10 +103,13 @@ kami_gateway 采用了以下技术栈: 这些技术的组合使得 kami_gateway 具有高性能、高可用性和良好的可扩展性。 **Section sources** + - [CLAUDE.md](file://CLAUDE.md#L90-L110) ## 启动流程 + 系统的启动流程从 `main.go` 文件开始,主要步骤如下: + 1. 获取 MQ 地址配置 2. 初始化代理池 3. 初始化分布式追踪 @@ -113,10 +131,13 @@ H --> I[结束] ``` **Diagram sources** + - [main.go](file://main.go#L23-L57) ## 数据流示例 + 以一个支付请求为例,完整的数据流如下: + 1. 客户端发送支付请求到控制器 2. 控制器调用服务层处理支付逻辑 3. 服务层调用模型层进行数据库操作 @@ -127,11 +148,14 @@ H --> I[结束] 8. 控制器返回响应给客户端 **Section sources** + - [internal/service/pay_solve.go](file://internal/service/pay_solve.go#L37-L195) - [internal/service/notify/order_notify.go](file://internal/service/notify/order_notify.go#L41-L109) ## 高级特性 + ### 分布式追踪 + 系统集成了 OpenTelemetry,实现了分布式追踪功能。通过在关键代码路径上添加追踪点,可以监控系统的性能和调试问题。 ```mermaid @@ -146,9 +170,11 @@ G --> H[响应结束] ``` **Diagram sources** + - [internal/otelTrace/init.go](file://internal/otelTrace/init.go#L29-L205) ### 异步任务队列 + 系统使用基于 Redis 的异步任务队列来处理耗时操作,如订单查询和回调通知。这种机制提高了系统的响应速度和吞吐量。 ```mermaid @@ -160,10 +186,12 @@ D --> E[更新状态] ``` **Diagram sources** + - [internal/service/supplier/third_party/pool.go](file://internal/service/supplier/third_party/pool.go#L16-L25) - [internal/schema/query/supplier_query.go](file://internal/schema/query/supplier_query.go#L89-L116) ### 定时任务 + 系统实现了多种定时任务,如订单结算和商户负载计算。这些任务通过定时器触发,确保系统数据的及时更新。 ```mermaid @@ -175,4 +203,5 @@ C --> E[更新商户信息] ``` **Diagram sources** + - [internal/service/settle_service.go](file://internal/service/settle_service.go#L219-L235) \ No newline at end of file diff --git a/.qoder/repowiki/zh/meta/repowiki-metadata.json b/.qoder/repowiki/zh/meta/repowiki-metadata.json index a1659f1..630fd86 100644 --- a/.qoder/repowiki/zh/meta/repowiki-metadata.json +++ b/.qoder/repowiki/zh/meta/repowiki-metadata.json @@ -1 +1,1243 @@ -{"knowledge_relations":[{"id":243,"source_id":"89d888b3-2b22-4be7-8c3e-66e1f9cef86c","target_id":"0fb51e95-8a1d-45fe-96b2-632c00da5541","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 0fb51e95-8a1d-45fe-96b2-632c00da5541","gmt_create":"2025-10-08T20:18:48.663272+08:00","gmt_modified":"2025-10-08T20:18:48.663272+08:00"},{"id":244,"source_id":"89d888b3-2b22-4be7-8c3e-66e1f9cef86c","target_id":"75b363d5-4074-4921-9ada-579b8f5a30c4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 75b363d5-4074-4921-9ada-579b8f5a30c4","gmt_create":"2025-10-08T20:18:48.6729736+08:00","gmt_modified":"2025-10-08T20:18:48.6729736+08:00"},{"id":245,"source_id":"89d888b3-2b22-4be7-8c3e-66e1f9cef86c","target_id":"5c05b03a-d7c9-43f5-94c6-1f4ea2793f19","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 5c05b03a-d7c9-43f5-94c6-1f4ea2793f19","gmt_create":"2025-10-08T20:18:48.6804484+08:00","gmt_modified":"2025-10-08T20:18:48.6804484+08:00"},{"id":246,"source_id":"89d888b3-2b22-4be7-8c3e-66e1f9cef86c","target_id":"70b6c90d-240f-4eb3-abc6-50fb7add6fc3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 70b6c90d-240f-4eb3-abc6-50fb7add6fc3","gmt_create":"2025-10-08T20:18:48.6888578+08:00","gmt_modified":"2025-10-08T20:18:48.6888578+08:00"},{"id":247,"source_id":"013b2790-e5e2-4879-8a97-c5dee7adde89","target_id":"13bd83fa-402e-438b-a012-6d53eac7c39d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e 13bd83fa-402e-438b-a012-6d53eac7c39d","gmt_create":"2025-10-08T20:18:48.696662+08:00","gmt_modified":"2025-10-08T20:18:48.696662+08:00"},{"id":248,"source_id":"013b2790-e5e2-4879-8a97-c5dee7adde89","target_id":"d0e098cc-486d-48ae-99b6-dae8bd81b609","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e d0e098cc-486d-48ae-99b6-dae8bd81b609","gmt_create":"2025-10-08T20:18:48.7049818+08:00","gmt_modified":"2025-10-08T20:18:48.7049818+08:00"},{"id":249,"source_id":"013b2790-e5e2-4879-8a97-c5dee7adde89","target_id":"8a821f9b-5ad9-4602-96c2-724299a01a8b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e 8a821f9b-5ad9-4602-96c2-724299a01a8b","gmt_create":"2025-10-08T20:18:48.7129288+08:00","gmt_modified":"2025-10-08T20:18:48.7129288+08:00"},{"id":250,"source_id":"013b2790-e5e2-4879-8a97-c5dee7adde89","target_id":"3077240f-f00b-4f59-a8ce-8991408c4b96","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e 3077240f-f00b-4f59-a8ce-8991408c4b96","gmt_create":"2025-10-08T20:18:48.7266219+08:00","gmt_modified":"2025-10-08T20:18:48.7266219+08:00"},{"id":251,"source_id":"7424e713-8de3-415b-ab24-f02a1102bdbc","target_id":"026c8458-a7b5-44cf-b052-10b1cd6604f2","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 7424e713-8de3-415b-ab24-f02a1102bdbc -\u003e 026c8458-a7b5-44cf-b052-10b1cd6604f2","gmt_create":"2025-10-08T20:18:48.7389167+08:00","gmt_modified":"2025-10-08T20:18:48.7389167+08:00"},{"id":252,"source_id":"7424e713-8de3-415b-ab24-f02a1102bdbc","target_id":"16f1ef56-d692-41dd-84d7-c41790f98abb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 7424e713-8de3-415b-ab24-f02a1102bdbc -\u003e 16f1ef56-d692-41dd-84d7-c41790f98abb","gmt_create":"2025-10-08T20:18:48.7470347+08:00","gmt_modified":"2025-10-08T20:18:48.7470347+08:00"},{"id":253,"source_id":"7424e713-8de3-415b-ab24-f02a1102bdbc","target_id":"f0a4a14b-8948-4372-a8b7-6974e4286083","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 7424e713-8de3-415b-ab24-f02a1102bdbc -\u003e f0a4a14b-8948-4372-a8b7-6974e4286083","gmt_create":"2025-10-08T20:18:48.7544795+08:00","gmt_modified":"2025-10-08T20:18:48.7544795+08:00"},{"id":254,"source_id":"6e2e98a9-36f3-46c1-b2f2-db52c4526f11","target_id":"302aea38-1949-48e6-bd95-96cb17b84d12","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6e2e98a9-36f3-46c1-b2f2-db52c4526f11 -\u003e 302aea38-1949-48e6-bd95-96cb17b84d12","gmt_create":"2025-10-08T20:18:48.7748735+08:00","gmt_modified":"2025-10-08T20:18:48.7748735+08:00"},{"id":255,"source_id":"6e2e98a9-36f3-46c1-b2f2-db52c4526f11","target_id":"b527099a-0510-438d-a4ec-b8ed8642ae8e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6e2e98a9-36f3-46c1-b2f2-db52c4526f11 -\u003e b527099a-0510-438d-a4ec-b8ed8642ae8e","gmt_create":"2025-10-08T20:18:48.782745+08:00","gmt_modified":"2025-10-08T20:18:48.782745+08:00"},{"id":256,"source_id":"6e2e98a9-36f3-46c1-b2f2-db52c4526f11","target_id":"f5af27a6-1bd2-4346-a7a8-2682705f09c5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6e2e98a9-36f3-46c1-b2f2-db52c4526f11 -\u003e f5af27a6-1bd2-4346-a7a8-2682705f09c5","gmt_create":"2025-10-08T20:18:48.7906626+08:00","gmt_modified":"2025-10-08T20:18:48.7906626+08:00"},{"id":257,"source_id":"d2d80765-26c3-4c0b-a302-612693077838","target_id":"3f30d007-e6cc-4636-8ab7-f10562baff6a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: d2d80765-26c3-4c0b-a302-612693077838 -\u003e 3f30d007-e6cc-4636-8ab7-f10562baff6a","gmt_create":"2025-10-08T20:18:48.7985877+08:00","gmt_modified":"2025-10-08T20:18:48.7985877+08:00"},{"id":258,"source_id":"d2d80765-26c3-4c0b-a302-612693077838","target_id":"3b453233-b2ab-4942-9a6c-d92a5a3897c0","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: d2d80765-26c3-4c0b-a302-612693077838 -\u003e 3b453233-b2ab-4942-9a6c-d92a5a3897c0","gmt_create":"2025-10-08T20:18:48.8065544+08:00","gmt_modified":"2025-10-08T20:18:48.8065544+08:00"},{"id":259,"source_id":"d2d80765-26c3-4c0b-a302-612693077838","target_id":"93cae8db-9a04-407a-8446-250cdc33f661","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: d2d80765-26c3-4c0b-a302-612693077838 -\u003e 93cae8db-9a04-407a-8446-250cdc33f661","gmt_create":"2025-10-08T20:18:48.8147799+08:00","gmt_modified":"2025-10-08T20:18:48.8147799+08:00"},{"id":260,"source_id":"d0e098cc-486d-48ae-99b6-dae8bd81b609","target_id":"b5f75438-5c24-4f0f-be95-f857806fcfaf","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e b5f75438-5c24-4f0f-be95-f857806fcfaf","gmt_create":"2025-10-08T20:18:48.8253615+08:00","gmt_modified":"2025-10-08T20:18:48.8253615+08:00"},{"id":261,"source_id":"d0e098cc-486d-48ae-99b6-dae8bd81b609","target_id":"4a9995be-1002-4a48-bf07-8b4f725756d0","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e 4a9995be-1002-4a48-bf07-8b4f725756d0","gmt_create":"2025-10-08T20:18:48.8339278+08:00","gmt_modified":"2025-10-08T20:18:48.8339278+08:00"},{"id":262,"source_id":"d0e098cc-486d-48ae-99b6-dae8bd81b609","target_id":"b2cf330f-309b-4fa5-980c-c5809a143195","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e b2cf330f-309b-4fa5-980c-c5809a143195","gmt_create":"2025-10-08T20:18:48.8418303+08:00","gmt_modified":"2025-10-08T20:18:48.8418303+08:00"},{"id":263,"source_id":"d0e098cc-486d-48ae-99b6-dae8bd81b609","target_id":"047d142f-ec46-4f80-83d3-c377a86858b8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e 047d142f-ec46-4f80-83d3-c377a86858b8","gmt_create":"2025-10-08T20:18:48.8549301+08:00","gmt_modified":"2025-10-08T20:18:48.8549301+08:00"},{"id":264,"source_id":"8a821f9b-5ad9-4602-96c2-724299a01a8b","target_id":"9c7904f8-0b4a-422b-806d-55c96bec2fe6","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 8a821f9b-5ad9-4602-96c2-724299a01a8b -\u003e 9c7904f8-0b4a-422b-806d-55c96bec2fe6","gmt_create":"2025-10-08T20:18:48.8672021+08:00","gmt_modified":"2025-10-08T20:18:48.8672021+08:00"},{"id":265,"source_id":"8a821f9b-5ad9-4602-96c2-724299a01a8b","target_id":"2500aa21-fe32-4057-a5ad-11fbd4d19546","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 8a821f9b-5ad9-4602-96c2-724299a01a8b -\u003e 2500aa21-fe32-4057-a5ad-11fbd4d19546","gmt_create":"2025-10-08T20:18:48.874549+08:00","gmt_modified":"2025-10-08T20:18:48.874549+08:00"},{"id":266,"source_id":"b5f75438-5c24-4f0f-be95-f857806fcfaf","target_id":"e50eff25-5123-4c73-8a3b-487293043f2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e e50eff25-5123-4c73-8a3b-487293043f2f","gmt_create":"2025-10-08T20:18:48.8845346+08:00","gmt_modified":"2025-10-08T20:18:48.8845346+08:00"},{"id":267,"source_id":"b5f75438-5c24-4f0f-be95-f857806fcfaf","target_id":"ed7bbb93-3e0c-49fe-b1dd-a92d8176638e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e ed7bbb93-3e0c-49fe-b1dd-a92d8176638e","gmt_create":"2025-10-08T20:18:48.8929564+08:00","gmt_modified":"2025-10-08T20:18:48.8929564+08:00"},{"id":268,"source_id":"b5f75438-5c24-4f0f-be95-f857806fcfaf","target_id":"243ba92b-7b56-4596-9c54-31905f65e471","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e 243ba92b-7b56-4596-9c54-31905f65e471","gmt_create":"2025-10-08T20:18:48.9007605+08:00","gmt_modified":"2025-10-08T20:18:48.9007605+08:00"},{"id":269,"source_id":"b5f75438-5c24-4f0f-be95-f857806fcfaf","target_id":"99e9dc6d-e943-4712-a961-7a053872ad8f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e 99e9dc6d-e943-4712-a961-7a053872ad8f","gmt_create":"2025-10-08T20:18:48.9088886+08:00","gmt_modified":"2025-10-08T20:18:48.9088886+08:00"}],"wiki_catalogs":[{"id":"3f5378b4-a8c2-4361-90a2-caf79aeba7fb","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"项目概述","description":"project-overview","prompt":"创建关于kami_gateway项目的全面概述内容。解释该项目作为一个基于Go语言和Beego框架的高性能支付网关系统的核心目的和架构设计。详细描述其主要功能,包括多渠道支付处理、订单调度、代付请求和回调通知等。阐述系统整体架构,包括MVC模式的应用、各核心组件(控制器、服务层、模型层)之间的关系,以及启动流程(从main.go开始的初始化过程)。结合CLAUDE.md中的信息,说明项目的技术栈(Beego、OpenTelemetry、Redis、MySQL、RabbitMQ)及其在系统中的作用。为初学者提供概念性介绍,同时为高级开发者提供技术细节,如分布式追踪的集成和异步任务队列的工作机制。包含一个简单的系统架构图描述,并举例说明一个支付请求从进入系统到完成的完整数据流。","progress_status":"completed","dependent_files":"main.go,CLAUDE.md","gmt_create":"2025-10-08T20:04:49.3551015+08:00","gmt_modified":"2025-10-08T20:07:08.687419+08:00","raw_data":"WikiEncrypted:0MI1/XkBoMl0lTbK6t0Cn/+8FdvqrJ62ianMLvZj02elJtBUgH0Ns0veIx1WPtM9wwkxI+/XAqHLxJLlHB8wV5ZPaqnpZD68qW6viSXvNxPJNDAD05FZhFLjO5QfwnFHWPmp8131gwmlV3+yUNfSuYNEWqrJ75L2XuQDuIDW0SOK99teLJoUi45zev+K43mRPdrh41HdJlZE/Jsz6+HE0EYNTTPdgFIWhJ2lfkhN6ub5MQ+yfytKxGTF0NG8E1tg+dZ1HeVX97YzoSV8ppoxUrbe2ZImsGFEojjXbvHGVyOOoqY4gCdFXLjVAAIKXNvwpbtoOdhlIwUgZqhdd3M2mUYoz1vTUEqzi5f2Tzht3uo7ndi3oVtIQjt7kNlcreks6wxImWgkbUgJY8S27IpbKbVdtRRMM9vWs1V6QxUSNZvAKnAr0qaCRbL5Mq5WP35NS3BK2wQhnRIrGRjBuOioB0kP6Ms31o8bl+vzVam9+QDLWSftKBX6XBWRzLf124p0BmkF9qZ7wReMn4fNvtVC6yoJM8TktA6XT9MsHi8eBrEaR7oF3LIG3nlIWKRWHJNQod+O3OglG5SJzuAu7MeFDq6fxHGnQXVJ8IDakA02Gf207gtl5UwjMoj15rlSeOqDEUSE7q/1BGZ7NceAs2/nhGH+Y4Sj0jXa19bFNspgcbc2mmSChYjkFdTkJ8f1N2RqsdywRfnAxsePQz34Cv4RcWawgK1rFf73QxegrlXZ+Bz/M+Ojzdsow5hox/ezQYbw5+LmStYx8+bu4uoUk8u3SVYql5x7z2//bYBaV/WmkQlxzYSHEx3pN9qMb9cdod6e599OeMLRY5XKRGBCaXEhdGO/Hd1dvC+1ghnNlHtAM+euctI+Xe4jNA+KjwkI58OBc9KrCag1IU1geZCkAyM6U4HiSMNVRhC9uiKWNhprOXPj6jtO5Dui0MhP/L8R33l2sR8Cp2L+pQrVyFV+GtFSfVvWC1eyc/qqK34F1P5BrulAgFDf8Kwc37rMwrMymK5tseELGRyKdNLaU1UvALyhXJINsExpwGedpUI3d6eN0qNCRdE3/NYy0t1S2BHKJM4w3QBcUsyUxdtWQA5EYoxn11U43hp348DWyiMgqyndua71AsT5XKKthljr2gmPSqRpGQ7c/pfzprYVPHDP9HL8Scqv7nmOWmWzR5kEsn9mPo9M3RJAHsYUw27U6e9LeKycWi2A3Bij7VKdyDHFh9/DV/3JJ0EPvj3RH8bzDpYrVzUO33qcnJE5Vt9ek+TPXUZnowOH9u4b9KLO9jj6oyBNf4km/UrHVC6X0DcoBkg+9ks9EuQ0URuKlPQO/uZR6kRhgocoyYicmu2IhKruaibS4lLTomlAtrNPScOrHfQMMzE59GFtT5hz0FRB3r7NxdAyTWpiZLM0HRhBHiLCbHnRR3HYyr3kgdnFaystz+1lm47pTzoFzSq6mDNYqP/CW7BX"},{"id":"ff8a9c9d-2dc0-433a-a1d4-b84ee2141635","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"订单模型","description":"order-model","prompt":"创建全面的订单模型文档,聚焦于order_info.go中的OrderInfo结构体。详细解释每个字段的含义、数据类型及其业务作用,特别是订单状态(Status)、支付金额(FactAmount)、通道标识(RoadUid)等关键字段。描述订单状态的完整生命周期,包括从创建、支付、成功/失败到退款、冻结/解冻的状态流转逻辑。阐明OrderInfo与order_profit_info、order_settle_info、platform_profit等关联模型的关系,说明其一对多或一对一的数据关联。提供ER图描述这些实体之间的关系。文档需包含通过Beego ORM进行订单创建、查询、更新的代码示例,并讨论高频查询字段(如MerchantOrderId、BankOrderId、Status)的索引优化策略。同时,解释订单数据的归档与清理机制,以及在高并发场景下的数据一致性保障措施。","parent_id":"a5d56738-c20f-4178-9f81-d01bb592f194","progress_status":"completed","dependent_files":"internal/models/order/order_info.go,internal/models/order/order_profit_info.go,internal/models/order/order_settle_info.go,internal/models/order/platform_profit.go","gmt_create":"2025-10-08T20:05:09.8999413+08:00","gmt_modified":"2025-10-08T20:10:13.3178855+08:00","raw_data":"WikiEncrypted:1TcXmWRnDAgI41cGfWTUk0mu632uXt6rCt+zlwbNXH3cI5ea0ul/gH1ctKZ1sOQGRugrR4SG9AWauLAeU1/9zDoT7NsiqMF9p74EyuzRsReCaZHq0ftesSjQISh1ms08c9zO/AxEYtaFLlQDfeRz7BKMoCC+i4dQSOjRgcas1dh1raG6BTLXjiJdoWoVDHbMqLf3WbcD+j8J5ngFzB87vyiPK9nC3cYI8ziVPFI1kjy7zs1Ju1D7zi5yjg1hyylSm+iumS45vif3MZSoeL7KOwj4JvhfOpDkNngKQDlDJ2r8gGQd32M/P9rDj2oFaOsLr74QWf/ShgrhFg9CEjk9H9safU0BFoVzk33kJXE4/eFrbQTYG1Ytw2Wyu2QVMDo5GsYyU1e7Rb75SRe9/S45LEsWMawreZmtUSkKOc2F2px+IgXba9xv4O/3p3JmPQ8Qu6Z4Xm7kx7W8u4M0qzxV6sNOK4C2jHqPEO05J6JbCkeS3GJlNd+bm3TGPCnOD5aV6EBQUkMhtZT2xMlHloKDRhV8ENaxqT4pd51o5wx9j6Q0Af/BslcRBQdX2F9GNsQ8XsarzaP+erN/pgjyeL5VIaaTKzqS0JNq1DDVlm4++LHtyfP+WaYcJGdtLiahwDmLh/oCy560iMUG+RZJLI2eCvcnH/PwvaUB43NJG9djkqYu+AzbDHlRHwXhdjmeOoiMKnb/MVfg1p2uj4BCigi6efzj4L2ziO7kH8bb379jlGZ1Eo5KVIbb4Kou1YZyqDbG4mz4LCAibtUHQy3Jtvw4FtfsvHAEF50kXj9yLEGCG4bLbgWnHOdYndyTEhSdGLU6dbtA+10UTB8Q/4tppVfEapBdDIg1qW0N1LFpq+Bnd1I3HlMqfUivuvHJmA38JpDDbkbjQLk+puMZevIeYzJirTNUDgJFLQy5NkdV1biKHw7SqSRJ6k9wQ0w6aQdDrPGiCEv35Wtk6LJTM1jvupmYoU1/RSP6Qb7BglHLH9BLlTsDO6eenXGr47ZaNFA/d7iiKTOayr0HZyAZu4ur9hRyqn1Itwc11aQvinP8LmEk3OPDxe/wi+lbw8Nm2UnNed0C+cly6YNcj1ArdlY3QsJ2rkzjxPd5ioOd7+sQyC+cQX3IJmFQM9VfSs8kPYDpiA8ykakv6xh0TsL47JoWP86WkDUQDuqQ2uLchVVAYFrWC554N8+CKUUXTLsBYmNnRLnP9SgD7AO/3NT+AnH6pXcQy/hnRZN4Q9osisJXeFYr8vx7NY/zwW5zQzZnh54HZ45XXpGJuNXcHelh5b1As/jgbqxWYuK+z9JcII3ppT39XzWfh04B27SOUjdeCyFyLavZJEojzZMQizfhEGx5PX2TrAWhdBI5/8Khc3PQv74nfaIATRT2FbHhPcerDrLokEmCiNbzTo72lD25WkddyQdWf3qSk3tYfjUB254tT4vZFMjGqWUpOyiDqRYl8BP0RplC5tLr1/+KbGahSAh4KE+d9IcafB0rPgABHUriXD8hQ4bLVcW+3YMmclGOGDKJTNJjTuKm31U/vGYZaExnq0IwtOEx+sHn5hgLD31Q/3p4JtmTuGwg4FEs7lIQaBnMiYJDspcQpP9xjwQh+5FSsq1Lv3ze2gB0fVWBRuC9i3n+2BWvgFBFSVgA9b+blfIAMzGxldcwxRfl73S6DcQdAYDsJkqzGTYoU8bAPFa7HYqTG4fUt7PZZKQavrWJkCLwENFF","layer_level":1},{"id":"a21144d5-112d-4642-a874-64fb8a1ea84f","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"Beego 框架集成","description":"beego-framework","prompt":"创建关于 Beego v2 框架在 kami_gateway 项目中集成与应用的详细文档。重点说明 Web 服务的启动流程(web.Run())、路由注册机制(router.go 中的命名空间与控制器绑定)、控制器继承结构(base_controller.go 的封装)以及中间件集成方式。结合代码实例,展示 RESTful API 接口如何通过 Beego 的注解路由映射到具体控制器方法。解释 Beego ORM 的自动模型注册机制(models/init.go)及其与 MySQL 数据库的交互模式。提供性能调优建议、常见陷阱规避策略,并说明框架升级兼容性注意事项。","parent_id":"576b2803-bcc0-4769-89b3-54c89e6b7381","progress_status":"completed","dependent_files":"main.go,internal/routers/router.go,internal/controllers/scan_controller.go,internal/controllers/order_controller.go","gmt_create":"2025-10-08T20:05:11.0590792+08:00","gmt_modified":"2025-10-08T20:11:20.9567628+08:00","raw_data":"WikiEncrypted:pYbZ5lRfULAG9jugU9XK63rJ8GPtKRTSEbtQAg5JLYWXJILzfHFhMg9BW6Hr9mzVoxQ045fHqDzCfMmueW2jL2W6NCEsvVpIHvX+6rH8HRYhUWh+pAll0hDV9OGuBX6B//sGA4Scx6WgPH7v6Pxji5huDlnPxiJ8XTKuYY/UX3HWMBdp+MHikW0btSfjxfOHXjTCT8QXqvwq95Yk90EH4ZsTtPqgi4YTt14YldgRFsqWKE1ZwNy5gcgkTxyVxKjxYKByJh9ppwO42retGbh3OxRKXjznM18i6EtUzq9kq7WPT62pjG49LYk8JDgR1uvpwkMocJ5+RSFSCa3rp9ww2GwDE6Zn7JP4kkXsMs/PjMN9NJNL4rgk3IRY3mvfMs7bETa+t9TMW2G9n3fn/0SR+9+xkiY88Uw3XsFFkqoMunWEiQjs9o4OQJQjlm9E3pQQO5tQJ+rBA5uK/d3Za5rTXYWYRZ9YxSoJG7Ljixn2OSrq9QB5Bymy5xjduCS+m1ONtDpsKumS9CUes5iCicOQx7J4lox6/a9dl/r5TcnIeEjtQEGTrjy8hzovQLoAeTTbHspfdqBPG3O3bkWP2Josr0F9nbV/9HLPYWJURk+GNT7a/ikul0weorlQyFnkoVLSoNKN1O4ROlxEywcd5bBLMWSDmnnjfnnV8hsQnGfdXnFpyy7AsxYpHMwYsqRCetnTY62QT5ytW14k89q2rpkcgVRNta4K/woMb+vQLCv1dC78gsq7iX/XeQ79wABLTsi0FkyF5BWAAXVX81dxj64mN5C/EXp3wMMZtHnHy+zbytSuN9chXtGdQl9XZYMeF0v/nsZUtxepBkgitrzfKfSYbTZLjJAlUKTQk5kPJmWSrZx83nwTRTCx42ecYCMOwqsSsGPi1YlsLTmFBJCpRnlrUuNFewRrPEfOIOyqGVeM4MG452v5nFeDoYpeJySc5XPryqgJR4L80OF9aSK6pXww8NhbR42HBhtUWicMiDy6+oCH/ZCbW8mWWpwnOi3miFcg3cfcQJ1EnRR/P0wba6K15KMO7exmNCe6cwfqTlptyM49qo2O/bwpQYZ7o9p6abSXXtF7Pfa8K3gnMd2GOyd7cI6DYEw0noI0tu6FtxKk6WY6Sg4jy0Xm0xVBXLSzqNZwiPlSAhONcEsvoessVgpOyYBCL3NFDfBlL+wAeeV7taw5WtfYCzpYwr1Uojja41QZTZlH6lLQa18n9JaH4wfKbnM1dzpY3TXkR+Pskax3PvkNaK2Kc8XJ09sI3eEZCeqa","layer_level":1},{"id":"0fd4a109-43f9-4cea-9416-4cd2bcafd325","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"支付API","description":"payment-api","prompt":"为kami_gateway的支付相关API创建详细文档,重点覆盖/gateway/scan和/gateway/createOrder端点。解释这些API如何处理支付下单请求,包括请求参数(如orderNo、productCode、orderPrice、notifyUrl等)和签名验证机制(使用sign_verify.go中的MD5签名)。详细说明请求流程:从接收商户请求、参数验证、选择支付通道(ChooseRoadV2)、生成订单记录到调用第三方支付渠道(通过third_party.GetPaySupplierByCode)。提供完整的JSON请求/响应示例,解释ScanSuccessData和ScanFailData响应结构。文档应包含错误处理机制,如订单重复提交限制和IP限制。同时说明CreateOrder接口如何生成支付链接(payUrl)并支持自有渠道与第三方渠道的区别处理。","parent_id":"80fb1e42-5bd2-4870-8b88-77d31ff5c478","progress_status":"completed","dependent_files":"internal/controllers/scan_controller.go,internal/routers/router.go,internal/schema/request/order.go,internal/schema/response/pay_resp.go","gmt_create":"2025-10-08T20:05:17.6527387+08:00","gmt_modified":"2025-10-08T20:10:53.955797+08:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JomSPSNlxixXQGITg+XBkQR1A651zRsXgTTzt7TTgrAOtmF6FZNGeCDV26qfOUdn+qVk5cL/IbKTPA9hIm7a/xk6pmHM6fw+bPPtDrw4oj2+zna4fs1ZFDyzNcZmQYGMwKCUXXliSL9bOvtCvSOcIJz7ACiI6Z381v4NL/F/u0/8GhMzWxqWonV4+P5FbRu+P9yH+TYARkHktb+lupqn9J/ezWrIBzOwmREpiphWwdTMs1pLjCYZOaIkazh/lSzn0K2ck1pkFCGSibZ1j7CXgiREdG6aWZ6AenuDccdYk0IfrzC1npbgli5ePCFXtVgIELr5K5d6IpDIa7z6MrG36oJG9NFgWpklgbA4uEWmvaxYJiJEVsgDwiZnM0gRRcvcPZoz2aDyRB/wzQvWeamL1Vx0J3wtIhwwuhqnN2GIeK8ekDMYjuYNVlZPX1RylDPH26MwB4BGtS/exe1mPY9FKcY6oVAi8HjPGY9+6W+npRBonWY7/Ye4QPlUc4nKx8YhN/u/aqn9yWe7qZtebAZDRmdUAxpRyCCN/xrpY0tYnMMHvX4GsR+y4duyKOiwNWbRYL8qhljUuOpo6EAANOL/tvu+KGA1gfE5GISxWQv1rBXQQtOLmiEXO1LSftIHvB9KdtJe8LBviMBhoIdCCuh58qWzSUcYCN0SgeNh9BjPuaTPLyW4wDyFcYR6STFQurOb+rgNYlu1/KMw9ufhUCR2StQTbWJW8WUuieoilsng3NsdiBxjZuzOKr+oplUs+bum1SYUZujRmrg5qDahaNSBicDhEa/jCsYELjMdDjIzZZ8y9gf+PmI/Z3A3lavT3vNtKD+kiPyOFocO3K9gp8T/PW44aoUDlyVRzfNExpc9qsCIOmAh2qx2fSnLp/Ormt0+kw1AHJEauHFcCsB4AOgcpe5vcLsd//vfNytudMaqu6nHQ8+icoUFH96PIl40PVFy7oOucQ7qj8BADWeMgWRfY3lbpXRMUhBLHufRGbfWTrj/9nLdQZXK9cxysYzmOoC2n+0t+k5Q+jLg820QKVNAoYvuk7ywkv0cJWOFXsc6jUIVYmL1PxE488GjcGkn5x+8mHUyb295l8YSGTUPTllMYyV6cp5L3+/648S2vw0c5R/xe1w0sYygJZ1jNKTmALxdoXFJMmxzGq7nstG2+5/4KuvwTpPm5EdXxWeLBGlfEK0yKr6SIS8ecx+97L1Zjo4FWZ3/SLpMrypCw3P+XxPpnwIjLMIWquhmJvWox8oNe35Cvg+fqJdNccOkxc+VKWgI5tkAoj3+y5QH2CVwZW9is384QQmzJLS5ewW5bZCQv1KOhtg2hHwaddn89v/QvrXmJ7WsDEfiUIGkVZT4QhCDXxlHsvJ/z/egTtw1g7Wwy9Ct0Tyb5GKfa1TkIo7OSeYQMxS4mp9TsvK/OYh25paps8KyoirIQVQgAYaU6ZYBERw905swD40jGWG3duypzV3+bzpFuFe6+p4/u6LzwAh0Tw8=","layer_level":1},{"id":"3d1b720f-a641-456e-94d0-ff9db2b5568c","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"Docker部署指南","description":"docker-deployment","prompt":"创建详细的Docker部署指南。基于Dockerfile,解释多阶段构建过程:第一阶段使用golang:1.24镜像进行编译,设置GO111MODULE=on和GOPROXY=https://goproxy.cn,direct以加速依赖下载,并执行go mod tidy和go build命令生成静态二进制文件;第二阶段使用alpine:latest精简运行环境,安装必要的时区和证书支持,复制编译后的二进制文件和配置文件。详细说明docker-compose.yaml中的服务配置,包括构建上下文、容器名称、端口映射(127.0.0.1:22309:12309用于主服务,127.0.0.1:22390:12390用于监控)、卷挂载(配置和日志目录)以及外部网络1panel-network的连接。提供完整的本地部署步骤:从克隆代码库到执行docker-compose up -d启动服务。包含常见问题排查,如端口冲突、镜像构建失败、容器无法启动等解决方案。","parent_id":"53d903ba-6508-45b8-b48b-b3d00d3ed07a","progress_status":"completed","dependent_files":"deploy/Dockerfile,deploy/docker-compose.yaml","gmt_create":"2025-10-08T20:05:30.6660042+08:00","gmt_modified":"2025-10-08T20:10:46.0280433+08:00","raw_data":"WikiEncrypted:h7ADvj4WLJHyulzCl+z7kMT6DzaQnlgZj+Vph23KSPwCAKwAGu81Jfoj4zRMdPAHAjNjzOswrmpAVwnZuFSYbYxSzu7Ii0/Kr0LYNoxQ/RWaQfk9+ro807nPoRs7ljBxN7ilkXwnmbx4F634qhI1CNLRXg7hNq4tA44hr72/A9I2hiD+R06jsyntF3qKEJQeDfWk6IFhSFlV19C6drfngvf4mbHMITqtO11BKZrNBJjQ7s/F4N8OqUMf+q0JK3ZPj9NcHS6dvX1S/9BgQRCeucmzAVQ59NIGfYIfUB++eZc6bqOBvR/0bhsXbg1Z5UTM4lQYAZATSC0H+xqVUFeSHIqyH3PxBDGA734N6DA/qScKpfOzeMP1uBW32BJ3dTtvVYiu8iurr9brvKUBRTY7/jX8e4RFg6z77DvqmtwarcLKBis6VcDL91n7VanPj4W+4kKzvwC6IXbR7YXgm2hOkRmnr8QzGqLmxyymsYNo2wXPs5scHaj71HDpzGodfDLV9HZkrhNyR9FN7sTKq+EzWEUlbd5dRqYQAxWquA+/BNVwuGBsUR/77Cg6gJLIMQkIxb08umxCA5W0ClnQ+LgP/taVUBy2529V1JlptjIX50o8SnXJf7dC7K1sgN51928Ci9r4eJD3Wg3uOh/CjqlIYl0Tf+W9Sjw+saqf2VHveQBijnkQfiYDl9vCtjlPWzzHHSTAgPiQqtwxTihbmjDw0GBBwmjzKg4DuBtPlQn987VoTMO9ep0jNnzOFttOu0fRgBMmm7DPRQwcoLHUaJ7teS7xwjKeMpXaDGY5k5O3ZEDbso+KcquJT6e0dVsVo/EHWZv7/aVPvdccDZREIcTfn2Whl5s+O4p9gCqw8K6gjAIwM/UgYnANXL9q7vNwgJoXlkrvvcLouD2jcerdEOKPdJM2rlln3Qc0vIqJDzwK6xSM0j4Hp6Pr6hFrJDTvfP75xHudMxdWe8JlBkaFiOQgHWt4OYjPuGquFpxMkneb3NUMZbpOUW7NxMDXRIGu05tokBrWbjjU6LRQsInAhSv5Y9G6ZMY1gR8EJQrf2ZSgS7QALqg8QiQ1PF0ZP/Bog/yf3/aQpZv64U11sRSCvxhWczuOlNvCSoGgw+OLiD2Xm/1bbE0HOs0OcOoVLSg1iQnpqjyR1f+GHj+Mo5xNeBGJrYmBFLDYJk/4orLuM5t2nNuf96bUs8V+NmPLmN88cqhCgexE9UdkDNRwonMAKXS5CSG0BZH8+eHgHS+DOighe6kKTOEimBHL+Z/TPSCXXc7mdFx8QDNBIpXkmWMPWxJ2a2n6SLJsJv8QelsFjdLqeqXbsQBQ+RAe1FCPULP5VyRpLfE1KaiwPZvnK50HZzvihNwrs4atWiwAw9B0uNEZfbdCadv4o2oiBW/37zUkvOLFzCPyIBc+u7l4aBLYSpzkGhDLIPNCKvsdFtsTVTgsgPj7+PggYW/QFbgqtUB+EUqrve24rgCKRe0er2ZaqJTy4aXQbHfhOqoaf5dkQPAKE9qAPUSfkfpVO0ZzkJY+2ehN","layer_level":1},{"id":"7cc42a3a-553a-4702-9eaf-b76dd3628a17","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"支付服务架构","description":"payment-service-architecture","prompt":"创建支付服务架构的详细文档,聚焦于pay_service.go和pay_solve.go的实现机制。解释支付请求从控制器(scan_controller.go)进入系统后的完整处理流程,包括订单创建、状态管理、金额校验和结果回调等核心环节。深入分析支付解决方案(pay_solve.go)中的关键函数如SolvePaySuccessByAmountDifferent,说明其在处理实际支付金额与订单金额不一致时的业务逻辑。文档需涵盖服务层与模型层(order_info.go)的数据交互模式,展示如何通过上下文(context)传递分布式追踪信息。提供序列图说明从接收到扫码支付请求到最终更新订单状态的全流程,并讨论异常处理策略、重试机制和幂等性保障措施。","parent_id":"1ccdc69d-fc3b-4d08-9be6-169095e4a163","progress_status":"completed","dependent_files":"internal/service/pay_service.go,internal/service/pay_solve.go,internal/controllers/scan_controller.go,internal/models/order/order_info.go","gmt_create":"2025-10-08T20:05:33.9784679+08:00","gmt_modified":"2025-10-08T20:11:36.0497918+08:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JvxO8KLLYdmkP5MiyHLrNi8YvD/ZlHRaEU+Ki/xv1XgB7U9taAOuEQEGNdrWJ4wheAmYaijjVKvdhNz58k/xaxuuqgmpOxt1if3RbdI2dvGdEAZ64D069hqGUue0BvhEJPSDLc74Uyt0t0yQFZNVE/dNgm4ZnN24YWN0mXHtGNGHCS/56OINC8R66Wk8e5tWvKmV/hef9n2CDeLrMDoBMjw4fw8eOQzsq42JwBaQOhdPY7f/73gdewEOeMQLO47psLUW26+elZ5HXh9RQZmDV/bLNvIJRarz4M3sY6UCP+4kGUCdLzOycPZavfQgpoJti7hsfRGFjJpLBMbL+ccsrxFPUpF4lMrN7d1l5HJgt2AYGd+48AUwqIw39l5VyCpwpSk2sU3wTNB2HMvzFFsJp2vorL98xgPnprBfj4rkCOZI478Pbbyh3XDf6nLpHqfJ7kMcf6c4/JF+AytcOWcVETEJ7FMHH9gvPPd5HQSNkhLhS/jRZ8j9a9enZLKBhcpst8AWLRauM8YdejEtnmq4Znq8UYEz7irsVB3ljOQdpdqLmQjl+dHonNV07hqykBrazJnsmsYEwIOM785CxOOmFihvUfeAihAwKAYcrrHMTRI4dQxIunztDxhQKSCWD6tnkfFogRAheU7sDglSFehycqHHmiyRdb/Xp/OGpzliowq2dk8m9VBGlb1rmiv6Q06akVr2naZa8G7t8n/pvH9VfckJbzsSX/V08kMOjtYoi99gLJqsrQmwdokvLluc8/mUmWk0sHD22lD3kZn6S9KJFM57pcUMzc/SkS19kmmzBvFQSrel3WU+5B78WlcmJMHqdCgT8EeTB1blK2Fekv6ASGYZdpfYQTGLphbTMRD4/OQzqsXn+F9zpE9yAieLZTn3iIimqdmHb43sPdtvPO/+8lSa12IgMDSbSUBIPdctiwpnkyUkkToqK0tj4X+EOxFp4it7uWTJuDjpqWF0Jq/f4OTv3nWjNHnKj4C3M4wiYGwxirwSQD/QmVWJEhpyu0KcpUilr5XlfYkqhu7K5nWxk99f3O53LJEoTnV4VqenpEJ3UlyEXVjPkBMfw4CAXpzxe7qUXnVfmQDL46vKyD0Bv+4g/faBcmSKIZ+IUn/6/UviBCkDIK6j9j9HVXZ+ZQ/PZ9nSwwVdQ6N44L5xlx6LKPS56PBPeC8T4mcLuOU7xQCzhHvEI9j6rPZQPGKalrrxbgSb041O+IgOir+TuzxzLhlJ1wWZcgnA+DFiFsUyb1nOHQvSX2gau5F00/mzJi6TL9EG2b7bPg8vGWiNSdpT2NmyPkQK54ve3wjm6lBAI1aEeMRasWqXadOlXpRz0TJCJ8fDj+oetsqJgPMvjkQRpyMVPLD4dVgTWU7nJCMtcz5NfDn7hyrJ+yk6E+vF9lLdSuEt3+6RiMD/fdPtFNDhHDndZAxlNVedF0GjVpNbk541bJcHvLCiwAFn0jaElwYLJh8cH2Us5g1+awnOfMAXzzSQe/nwhB7KaPAzQ8wWgz0wVVsa6bWR+13iXp3Qcm8ioMeL1p6CUbeuT4vWO0j1ZF5/WsOCnMPGki1QdK5gPPZpk2IKWlgdsOAwieq1IXTqIQ==","layer_level":1},{"id":"18826686-b467-4bd9-879d-73a780854d0f","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"MySQL数据库集成","description":"database-mysql","prompt":"全面介绍项目中MySQL数据库的集成与使用。详细说明通过Beego ORM与github.com/go-sql-driver/mysql驱动的整合机制,重点解析internal/models/init.go中的init函数如何从app.conf读取数据库配置并建立连接池。阐述ORM注册模型的过程,包括所有实体模型(如order_info、merchant_info等)的注册方式和自动迁移策略。解释数据库连接字符串的构造逻辑、调试模式开关以及事务处理的最佳实践。结合代码示例说明数据查询、插入和更新操作的实现模式,并提供性能优化建议,如索引设计和连接池调优。","parent_id":"715db9db-8d32-4ea3-926a-b56c98ea6d8d","progress_status":"completed","dependent_files":"internal/models/init.go,main.go,go.mod","gmt_create":"2025-10-08T20:05:42.1248852+08:00","gmt_modified":"2025-10-08T20:16:01.6849372+08:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkOuWrAhaS0tPjzyqDTq2Vay5iwmSA9JizrW27BQzawvuWWwwKTBqVtMcPa8A931hekM1drvtyY/U0a3Ubvw/hWNyphDgrlmj4meDkJISiqobL8+GYQA829C8PSu7plz1gZK+M6mt2ep3Y4/L+24ulKB7CwJDMEm7zYcSjRAC1eSkFRY2O3gu7H21I2Pn/Vavn+OIDK6IPknOlVUjqHan/6wYN3Cw9hztjomYiNZDdTykm1t+oBAPPa4qYA0ELw7XE7MDqAxDx7QeCCz0KXk/BJ2xk5I+tZfStWVrDWvBFmgB/B4WokADCF6WTN9AWsR0wHpRcLSqKDN2aQRe8ZdSuWogtg4zfVS/QJAVPlCHDQfp4AVJ7KOuAX/Cr0AER6nWMVLonjL8nxfyzyMn7fkUwY3brCf1+ryQF/LzwnmhLz5Cc0Wy9aV5/j8ETTu8si6nz5Papyuy31Sexy5y/rfBCore1fpAjAgyMOZdc7zsDGy29LOGdjLa5bMR3SSWLG6rno99ksyIRDMTmsGn4wm7NNMtr1ZvNbq0D2yNpMtyr4SR/SS/bGKoLIyegI6WqXEz5HveT2CPs9/vnenlGNLeTXRekydXA699Wx0JHvb+UB/uGubCVjVjJSryJF6ijo9rjLrFihmuhcXDfPUQCn1YjJQQGp6m32+bP6dCsV+wVvUNpSsisB4Y2TMKFVTUaa+FCsSIpbb0A4ZqR1nZ7gDiOj59sKLGwhNcVFDo+RaNEuhnyKykqHj83Pv9V8QakMOXkehrpx6THGVFmSM/84TN/KzJDel0cZwnLxzoe+9r7t3/AlF8pDPAzeFMJFgJUlEkCJG1iayaDNphAnHHqejTHLCnZXIGGk/eDkX1r5GybSEoi6UTkz+88KHdl3WXiPvkOAok1CyO2PaJ2+3fBM0zDzfCIAuLxq/N2dN2ch5Nzf5LjFarm8buW/8fOZqmExaXvNudP7+a6jGZ6CP7ERCxA9yrwuMGGwR0xiMKDcW4lmHeWbT3ofTCr88k3hR4dyo7WWVUE4u6+OU4qNgPtEB+LM21Nw9W3tPSdgM0zKvVmm6c6Z0vA+XbIK7VyXD4sVcEF/B8jlH9n3MBePzHvsoOr5kVqr4bmx+LSndC8rgvfcB7VFOLdSayjHoQE4pkluxtXDENbgFdTyXCi3/I02L5eqQ=","layer_level":2},{"id":"0ebb9117-99a5-4092-862c-49ee70ccfee0","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"初始化与资源配置","description":"opentelemetry-tracing-initialization","prompt":"深入阐述 kami_gateway 中 OpenTelemetry 的初始化机制。详细解析 InitTracer() 函数如何通过 OTLP 协议连接到后端收集器,包括 insecure 模式下的端点配置、5秒超时设置以及启用 gzip 压缩以优化网络传输。说明资源(Resource)对象如何通过 attribute.String 设置服务名称、部署环境和语言类型,确保追踪数据具备正确的上下文标识。描述全局 TextMapPropagator 如何配置 W3C Trace Context 和 Baggage 以实现跨服务的上下文传播。结合 main.go 中的 defer shutdown 调用,解释追踪资源的优雅关闭流程,并提供生产环境中常见的配置参数调整建议。","parent_id":"fd2a2cba-0887-44b8-93c2-9cc9e520daae","progress_status":"completed","dependent_files":"internal/otelTrace/init.go,main.go","gmt_create":"2025-10-08T20:05:46.2376869+08:00","gmt_modified":"2025-10-08T20:16:13.1309194+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoBNgZfVE6UWPLy7BvwoJmilxKC3nK+Hn9GFCHp3LlMh/2fFOlkKo/0tBDtOTUrZ9ljb+mKhjdJsDFYHHL/MuKc12eRv+grt9cb3fNNhY+gn4HsZIfFLnJ9JFfoHtmtcbxIC9lsVC917nqaTUMhk3Kb2CnAEIzU6mLNyLZ3ZOAboOMv1EHQF+N0Xs6CvJ8TFgImyFrtZl1SaJb/AIqr7Qt+du2pJAgFT9VZUler49LJeTbfZXoEtxDwDXDj/OSK9RSnalmkinxulQJq1C1JpUyDwnyJUWLCVwpnENXdvnVn29HA6ZNpAJSgCnDFCOvZmI14iLIH7R7RGfNygLIshyIVvaJZlaMAubamlvDrM8OSUgUqJkLaEwCrFeGkelRRO+niPR3naoXs3ZpBpTSMP5kEZmVOPvHGz6Hi0N/UZloXFXqrz+/D07L1mZ08CM+HB2QgBdAi2k8t3Hsk4DkwipVPcRGiSPjLfpXnnrbmTpP2i3fuJcPIqMr/3/pigWa8uaKGVx4hxslDLdjbbmAAv7JpIInRja1Se+6rjaQ83PC4VFCI1/HJLmTyAq0OdivGYXp+D54xV14LtW4KAr+cOaB/hFFqijwp+yj8MISVYEqjXhqZkHe3F040/UfbqoFCeoYD44qTFFLDSJjc1Tk4vBKKoMo2ZlgROKdwyN9zQh1LjlG2UzqdNRQC2aBkBgB6IExOZZ9GZFvBTcw3W0gFraMkk5IghKWdkb3IvQBpu9hnvRSG3rdw841EqLW+q5o4H6/EPzy0IcxhrriWwbgSbxXexFEhYGmLNnV2zxtLey3ahQig2n4XqTLPTONtozgVYVrX47eSERhFpKynWQVlJo+N1zlaF7iBz25akniummF8UEOohwwn/4+5YvaILGDkIM0fuAtxGjRCjdc1KbXaDNgVDuMrjE4F1l+37Bkth6UIMhA4M0vLtX/TsWGATX04nXEH/RR080K779IQTU2FFRpLPjiMJRIB851SNF9TcFi2zOppoT6ZeN+z/zdFk0F9Nw8I2bp8BnvAS27oVGqaTOgrqE++ygl2GtuZSQLlg0JqlafZ+YDzhH2LbaXV9bVIUW5qdTAFYRYWxVkxYpBkSORnPvmXKeK5EydFcf/QQpgNc5Cqf2DKg3Uxaamc20qxG7Ic1lBKHxcn0x4exqWIBb4hJrbXE4WHl4YaACWmQGUugIGxkvCd/rLltoH0KdNl4t8qq5LY1s54M47/pkByrs0t9cZRL1EAL30vHkuXfxrEWpgEa5kQY7J7t2wl9dB19f8U=","layer_level":2},{"id":"a85503ac-22f7-4a7c-946f-359954121de8","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"追踪导出器配置","description":"opentelemetry-tracing-exporter","prompt":"深入解析 kami_gateway 中 OpenTelemetry 追踪导出器的配置机制。详细说明 otlptracegrpc.NewClient 如何通过 gRPC 协议与后端收集器通信,包括 WithInsecure 模式下的非加密连接配置、collectorURL 的端点设置、5秒超时(DefaultTimeout)对系统稳定性的影响,以及重试机制(RetryConfig)中初始间隔、最大间隔和最大重试时间的生产级调优策略。重点阐述 WithCompressor(\"gzip\") 如何压缩传输数据以降低网络开销,并结合代码示例展示导出器错误处理流程。同时说明 traceExporter.Shutdown 函数在 main.go 中 defer 调用时的优雅关闭行为,确保追踪数据不丢失。","parent_id":"0ebb9117-99a5-4092-862c-49ee70ccfee0","progress_status":"completed","dependent_files":"internal/otelTrace/init.go","gmt_create":"2025-10-08T20:06:11.562666+08:00","gmt_modified":"2025-10-08T20:17:57.5854974+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoCfHd9R9oAxkyPItBnu4Jw+et5B3yBxu/abaXpcJpT2OpYOTlDjSqQTt9UmeIFX4bHn6qCdbRkbku1B03GjLzAD/wi1PAhMi80uaSAD31wmE097yPhnpfU+DxJQJ08KE7FS/quvhjPngLe+4dZxwDIrD4pLvJ/yZnFI/8TdnA/7agajUPQxW7dlAOD8yOhxnzr4gQo0/3JE3JrKnzjhnUKLecsEBn9sU+rA4gl1ndsG/wiWmdOXpf1FwCTR7lCszEvZ6rvkaLi1ypsrBcRu378llNkaoQijJVaLjRuYFM8lFS3+7BsMw3eBmX2apEt8feBU1AOhwSjq2asbPFi73CAdgfzCYom96a/1pAPuKyabBUui0pnSsWeH7su+4QapKlnkh0/GP+ugcHBqoFhQr5G79wR8C2tTZUD5bctP+yc6gQucqlGBtnDy+HgioFQGkWDewoGRpFVVs6OGohLT3kBIG5SQ37SOCFfe05E3FGygZpSAVmD1RVa1yzdmT10oMa7wNVV79XtFa4O0qVeGDzYYYEu1WmYmwHj7RLdLtfpGvMUsDfx75igcbzILLQt9ag541qAgQAx8YVUgp5LLOjN5FoHKKerFSrNJC2ufVvN8VMQND5Xiw5FuBNqRpzyp5LwOaeb7rpMjtu3Ks5uynnXB/5ek4wSzkRETayPqwUexS0v6fbc8JnQl7inQUVcyMulBcqSIXMJ3IQCGML7wa4erXyDu2Ct1SjW26buuTMtWW8J/c4Q2wZnnjO6L9cKDxxNC0naQAGOimW+WiW6F1xZ6tCtZGpFWQkZe6qqO+uVT2+8I4xkwPfTRe3i71HlrnD6wRGNTgUckphXflI+cMx7W77UuNGZFhZJS6aBUwq5B3AZj1In5Lu/Ctdp6w97L6CJqCmEeSuY0T0c7dp4GMZf8Wy/wZ/hRuFUbpilg2HqomfeRYhh9Z7ulXvisGVSOEjnQTOt8CkbyG/GZXClVyEqn4r5X4HstYl+/EnfWV3axx0YsY2MxB9f1r9zeCqbI3UbpntlF2Ht7hC+Wrqs8P/NSooxc2vxsNJ0kARDNOsgpNaKfMfvnqBBAdd4MRjRu1sOEk+WxM2GitSkmhhkEHpHwOjoUzVnGkEcAt3xQxC9Jr64oFkrDzpYeiRZabgGK6tSRfFbJOCQHtuzRaGzwbRzfMK7FGYAt9QxWeBxN41HZFurr/dBRgdRKalCUSRzI4IXE2sLf45kJb0Cv3Ywrmp4Y","layer_level":3},{"id":"576b2803-bcc0-4769-89b3-54c89e6b7381","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"技术栈与依赖","description":"technology-stack","prompt":"创建关于项目技术栈的详细文档。深入分析Beego v2框架在项目中的具体应用,包括路由配置、控制器继承和中间件使用。详细说明OpenTelemetry分布式追踪系统的实现,涵盖otelTrace包中的span创建、日志集成和链路追踪上下文传递。解释Redis在缓存(internal/cache)和代理池管理中的双重角色。描述MySQL数据库通过Beego ORM进行数据访问的模式,以及RabbitMQ在订单通知和查询消费者中的异步消息处理机制。结合main.go中的初始化代码,说明这些技术组件是如何被集成和启动的。提供每个技术选型的决策理由、版本兼容性要求和性能考量,并给出配置最佳实践。","order":1,"progress_status":"completed","dependent_files":"main.go,go.mod","gmt_create":"2025-10-08T20:04:49.3828695+08:00","gmt_modified":"2025-10-08T20:08:07.1086917+08:00","raw_data":"WikiEncrypted:w0CkdCdnXCcvlN5xOpiEhEX3U68GI0Ngj6azFMJo9xQD0Nwsj9XajeArLn33w436LuYJWl4xP0dT9zLNODhOpJWtrSnsTOFdbU6xnVdYH2VHdxM0TVYkDKgZ4DwrvVuCMH3n2Ln0dcHA1r96NDT6WyBdnOg8joNlX9Czav4oRaYEd4X9C20dqZf05sPUDqMBk+iAD+QXPK7Oul1xlQpPAgwJ5nXyPfpjzLwu8i6qRiGvlkS9cq2DjI0w7Ncpq1tIF/uAu6Lh9rG9c+gZxgVu7kylK39sk4tndGjN9CYGPm1mS28TvRdAkqLgL5lp3wg1A/dY4553gPHLUa2Z3tS6+Gz3AZSgR9Yv2T9pKH5gY+W+I26tkGst6njmIBiOs9QmrBV09gRAT7vmilTYSzZSPoI9kZcffd19a8sguQyUaBiZ5qx1jp5KgTZCInV7Zuvoq2vHfvDutu0pth226C4ed97O1PjHi8LAFM7pIkTcDvQC0mSylJpeDvdFCdndhZBgsh30YnrxeA4k77Q4MoZxM3vyMKraAsIHFBAht92ll+eoaSQbeaUM+pVNhyjhmUlKy7T0FSPlQKIsBKX6f1/4GCcKEFmXANFniryNSkDgYJRiBv9/y+giTGPqDsVq0RbgDywPXhvduPsiyGGdbkv1E5s6daZJPr10+UORd5l6IWk5cujJnbxLaZ91k85J2GygSkAugJs1kJ5QpTL6l6O1lj0+0JQ+evb8pCfPHi+NBW/IYxNm0+UIML2hW1GTwDl0TTnNo3iex32SRmY0XKcdRoH399DbFPsJxHqtEgi+thl6RH8DT2/RVykXIbxWVXBXx4Z8/lcO1kGty2pgnI6g159jzqIdq4U2ovKSHJE5FUObCxtOIPGcUXCyO2lzAApjNsSL2gAfZBNrHP/VKDxJSj3SPWEvaH14krJIE971JAUBHvNmEa76UbtqiVMEncqA+n5u4yXtd+D/aYIOrAGCLvVHKQZgFmJKMFPh0QrQBexoLdkN7k9YFuUJxKEFfbsPJlNs1Cd9UAHrtPASHas0/BxJqPElUYlTXWimVjbvO+V4cQtYFTM25RrTMrOf0b7nzS8bdZggQZTwLFFphMg/tyzn8MLJBPUMj5lFFmFg2pmzoIJxnfMapbW2x0be//h4wW8FE7H1wMjZz+ipTaorh0smyGzaUFnE+vFiVpK+1c42raKOO8nHl0CziBYRze2U+Awo5+G2kRDj9inJig8q5qr5TtldA/Xa6yitcAWE/bteykJcnSkcP8Df7Mxh6MGYWI9/ffQsQZBp3wbpZJDK6LOZp/GxkghQhIsbrqwNfqQs1Zg04Iqle0Qd+qStx4csZ6ieOhC6LWLWcK2F6438+ixkXauxoR+U5X3d+EcOugM="},{"id":"062cb25b-369d-43d0-b6d3-96447d99b3e9","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"商户模型","description":"merchant-model","prompt":"开发详细的商户模型文档,以merchant_info.go中的MerchantInfo结构体为核心。深入解析商户状态(Status)、商户密钥(MerchantKey、MerchantSecret)、代理归属(BelongAgentUid)、支付回调配置等关键字段的设计意图。解释商户与merchant_load_info之间的关联关系,说明负载信息如何支持多通道轮询和单通道指定等业务场景。结合pay_resp.go中PayBaseResp的MerchantInfo字段,说明商户信息在API响应中的使用方式。文档应涵盖商户的创建、启用/禁用、密钥轮换等管理流程,并提供数据库层面的约束说明(如唯一索引)。同时,阐述商户配置的安全存储策略,包括敏感字段(如LoginPassword)的加密处理方式,以及白名单IP(WhiteIps)的验证机制。","parent_id":"a5d56738-c20f-4178-9f81-d01bb592f194","order":1,"progress_status":"completed","dependent_files":"internal/models/merchant/merchant_info.go,internal/models/merchant/merchant_load_info.go,internal/schema/response/pay_resp.go","gmt_create":"2025-10-08T20:05:09.9098578+08:00","gmt_modified":"2025-10-08T20:11:59.3151984+08:00","raw_data":"WikiEncrypted:3KjeyWIVLPDcIZ9hw3jQx0s+bCB627XZhXTUJbQ7hcudYl4JYt7Lk3T/YXtQyNEOebfqZr4ySdA4jUgxPqVciOktb63n1C4D2sywUTrIxWjL6jFk5x7uESW/vsAtm3iZ3zCl+0BGdPNENAZA5RpWB3slkk/29P0WI6LBneZYGk+Ep32ikCROywH0KFSyYsboPKuotCIc2T0mAGOrU625SnKrNnZlHlvCCVb2LVz54P89GOXIW4kCtPQELQySZCFllmPYQA4JvpLOJt+zOlIMiuTZdUcaXdAyV1vZ3/7v65drFs9+KYmivVoPeC5uDSqz+uhIcD6lQOk98CBgVObIFj8kHAhhlFuY5N24uWLzZmyZ0+YTNEeWDCRM0+9iKFKxCQQ5upHjlfQqBLS4VLXO0GDYa98ooksjv/Km5KtSfXIKwOV1dT9fco6m4036seKKRjMCCf8h4Vg0V004q2KNfQqLPFEmmRtetlBNTCsZQmlYRGcNnKJiq8KpzJWuyjaHAolsfgR0DkF2sYdn+01oMcCh99HLFQEnAoS6x2QkSv6XJ3g6rZ52kQKMH5iTyjlahk44VBU/bT41AD/cOQNQHCbvhlZVfeIIRUR/K0zGePr+Ri90L2xcrB0FHlgQbaE7o1zWLQbtCXr0U3CFbys5efY4EscKltGtQPkGw1sn76qvu2kyE7QJPj1RiBJIxJaEXfkBG+or1SCT4lQQYyKszi4zkBhvXjg+mgqaNtfi54sKR3Pz024VWOf62swmjOzczmhFl1LQxZ4MGRlLFEOmpiPTAnmVhphShb7T6G8sHr+8OV4ze1XWrmHaqZco7nfDTnHtfvp2UIxblvWbM9P+3gJXr9U/Yokz9bv68urPaS4HbQKKuJgHQ5mm3M9tVnbFlkvfE+niKh3L51Nhiwo7koWjKbqMnOS9pdbrPVBakL/yI6Xh3+By2JIklY/KjQbNxhF6xTAtrtThMw4TZzQCYVHsRWckQyMQZJLzzGAmPrJ+CFRs11oVySBZSmhZPWdqwewatiD5KwPYjr6tB7PxPmr2Z562DdutatdCUvT2t35el393Pj/2jGj0M4W6O5x4IKGD5fFyPT8y9WrgzC0iXc4cv+ZN1J2kBq5IqlVJSINYV1d5LObBbz6kAAFdvc6GUeUlSx0jhodLv1NpLLkCK5HmATo9JCyVWFG2glhvehTnI1/rY1cMREEdF39Dy1lohP1k0z2SM4ujeDkAB2iMIsbuZ6ceNSRO65YJKNSJCuqSzPn7O+7DbPAPUDjNR6lNOzZf6vJaG4zNqvSPBy6OS19R3HnwdxDrUNzUplyMfODZmSkaHLFTikIO4RgByscl01BySTtgf0ar+ewLrJz309Ctkkj8+HtM5+c6UITyjkoSuLJTrhr6YZuIZ915fZtgBPXMlQrQGxHorXRBqdvlwtCS2+PrePo0Lf+qlFnjaRH1OyscfJJB8I72FsUJNE0HV+dKbL/+a7mCEGyju63c1MTtcg4k3NQl204KLrGiK7YuNui3ptRS1wud7aVxgtOOPUJCwnOxh+2otombyPCTGvLY3B6lM9xYhKq7ygF90qcnBegp1A18fBUiR1M8HWK2","layer_level":1},{"id":"fd2a2cba-0887-44b8-93c2-9cc9e520daae","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"OpenTelemetry 分布式追踪","description":"opentelemetry-tracing","prompt":"深入阐述 OpenTelemetry 在 kami_gateway 中的实现机制。详细描述 otelTrace.InitTracer() 初始化过程、全局上下文 InitCtx 的创建与传递方式、Span 的生命周期管理(span.go)以及日志与追踪上下文的关联(logs.go)。说明 otelhttp 和 otelzap 桥接器如何集成到 Beego 的 HTTP 服务中实现全链路追踪。结合 main.go 中的 defer 清理逻辑,解释资源释放机制。提供 OTLP 导出配置、采样策略设置、Prometheus 指标集成方法,并给出链路追踪调试的最佳实践。","parent_id":"576b2803-bcc0-4769-89b3-54c89e6b7381","order":1,"progress_status":"completed","dependent_files":"main.go,internal/otelTrace/init.go,internal/otelTrace/middleware.go,internal/otelTrace/logs.go,internal/otelTrace/span.go","gmt_create":"2025-10-08T20:05:11.0709854+08:00","gmt_modified":"2025-10-08T20:12:14.1173282+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zS255cSRc7Lla1AgWnUNCCp0pT3SAlQqtM1mavRDSLdAMtw+oajNwFyk035PdPByHpbY7qQlJcUnSpyBJ/rF8hhHdHYX3mPyTtSLEEGr80oDbXf47oVMzchbqsPcBwWhTr+LJKyfp4S2XIab1diWXldjIcfJN0c5B8T8cVXOI9HrP6DGpR0zDWVsfN1DLCorQM20Yj97bgr7lkfk4DYONyfiHh2xOn6srjcmTuz1UXUwrHBqsQ4oY18GRzBF6k/w0Wq0QiZ8Iezww2adbEnLGJfp441LhU4LLjux6IY9tuhIQMbnpcr9R98jWFitbQDsvMlQsJiBUuC1e28xycADMAH8bkK4gFTJe1yxTedXnNpKwpJ6qcRlouk5uy7d5d8h51kEVEcTFYHfSSgpehVD8shGdcguYtRI/hCyXlcLtCPQr7xBgUADycqI/jnmI17zxMucJlimN0J7UtEukbOfr1v9ckm+v51felPtyqYlrHVWJeNhyrD7KlJBYUnZoMNDmPq1e5BEMQqU9pX+5188sVZMLn/7fa4dCQkcWntmzGo/prTrNLLQ7qJSunNaUlSgWg+WIXORc2O3+WNhumLUZUsSioBcZIeW0DxSxujsOK6LqamHvjQGmf0a8/b7NqSmENeL9cfrM6gL+mj7G9IWy2fpGhy/dq8Z/TUDp9CD5Vi/p2YBXaVpceKm4Cbl0gIe1FXEwg9xfoRtqD5LPRE7Yrem/PE/Z/5jDHlQdMSrL93QFEx86IYSGAGoQk3TztOso5lS7Lni38SVlz25SOcojipOLpFrkn0u1hYNFxYktw0KtRmAgxOIcx3fyqJwCLYd3srCEoq3h3c5vuyLS+o26vdyLD4m8UaPjqyfvNsjCCmFBsoJoMrZC+7BSZ37MqgkCiCnyxWwpJWVME7OH5gkZRnwSlV6F0QGFa0KJY3LTSzj35gJi+WSqrAHs8EB0oa43zHvpOpcNvcbaHIK9zpqUqMkJJ95zbK3DevIGBMTdn+ehYSW1N06BR4AF5oyR6feORMh1m/bGNzrJCnOq3aUNBxLIA/FXa/b0VIqf5vx6vGEx73ThIsY5PP1/XSkH6o2dJs5RtEWOgSwVd0BuNxe+VjEgosfTLcTx0VLOyVnT9Q9ExfCcR1i3qJHcJ5/HZziDhuJW0aF806uAG4UKAK3p4P+1FTJlUn5Xka3mkB6wm9gWOAJAZg9BkU2NY02EH2vYYh32wZE7u8VLFiZo9k+tJpHDC1lcD3RN4yMgmLBq4HqmS7s7XcXs/mJfKSraqGXFA==","layer_level":1},{"id":"c7928cce-8e94-4629-be4d-3af7f5d251bb","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"查询API","description":"query-api","prompt":"创建kami_gateway查询API的详细文档,涵盖/gateway/merchant/query和/gateway/supplier/order/query端点。详细说明MerchantQuery接口的认证机制,包括appKey、timestamp和sign参数的验证流程(使用GetMD5SignMF方法)。解释如何通过商户密钥验证和订单状态查询返回结果,包括订单号、卡号、卡密、面值等敏感信息的处理。描述OrderQuery接口如何为上游供应商提供订单查询服务。同时记录OrderSchedule接口的重新调度功能,包括调度条件检查(订单状态、创建时间)和调度执行流程。提供JSON响应示例,说明成功和各种错误情况下的返回格式。","parent_id":"80fb1e42-5bd2-4870-8b88-77d31ff5c478","order":1,"progress_status":"completed","dependent_files":"internal/controllers/order_controller.go,internal/routers/router.go,internal/schema/query/merchant_query.go,internal/service/supplier/third_party/pool/service.go","gmt_create":"2025-10-08T20:05:17.6697413+08:00","gmt_modified":"2025-10-08T20:12:22.888047+08:00","raw_data":"WikiEncrypted:l9Ho0Yh0r5bYH9QEePEhke3k2RN8gG332YdAL7KtHYbPchW5eM3k+qEo35lenQE2nhqx4oft+lvdZUBitrIuXQfU+1iktwQUyRE6Bc7n1fYB13gGuhK1M3sz4QVwxdcnKErZG4FBLKWsGrCS6qpr+Mn7rm87oLJOuFQn7CEg8HszDhriQsCptiOxA2GY6/24ZnuOB4LEPaMK1GTdxDB5hHQFW5iMUXuXR0Aq9K9q0L1+Goe5ezSmYNw92YTAwB+iJmUFjj664leLuOuPOAY3Ye/EgRh4QqLu66rnal8yok4CLABJSShhCUQX8T8wXQkc9S2HZ62fOb5GzJT4zUx/Vy6KaBHIZv/3M9wc0wUdgFTGfTAaLNo//xa//mqccFXiv8sxFf/gnd4zFIVBIlJ5e96CYGGPK8m4vM4UyUYvRYUff7lN5++RSUKNJ6Dqt1wwCIkbM0g9TV8z3JIIc2ZntbJ/mvyEhvumd5RwGA1cjEnli8Cbj+1je/dyJOqjY4m2dP17yksS40IigFszqVseWYk/SQVkL6gx9sw/TMtocwZKxFytc5Ng2ZMAhwK7k6TmTttzFY67Pkx8OhyyJ2XmDzFumLSkEznqq+S+sQ6OIWIVieI9j+R1OzS+DyCmktHQF6fBWCAa48wYiX/9zi2wOB7MtM/4exXLhWeQLl4Bby57z+36TvVxhrbLAbqdGer+3DGgzcS8+yasvn5gtHZVGGADCtBQEPSnmbI7M4t8SMh2XeQypL3/t+WCzW3FnH7hmCEwggXYkLvsUng1GT4/q2TU5JDHGIZtbB7zL1R4ooyf4I4SpkA3ZawUv1byVTlZ9RVnPYfXRU334eCRmn2UAd8vkOlA3l6up3jeQuHT/8XhyeBMJbfXF6qcI67zIPOByRGvtvYpR+I+Y1yrVKGAJ5KNQmtHp/2RqAy3LtmvV6mOM9OHCbW/eO9nXcOO9LIAg1aRlmwKR2n1T4ScZ6MIhoe/BQoCR3SzaOMM4z4e8wPZUZ/qTbkD8OZcDRxy1qxcfarRbhSWTQvugSNjYz1qwE6IB3tH8FP2KSeiD3sHz9yq+GLfvkK/H9pwWcieLooh48LzBTfq67m48iegzDEGJCCwwrJE20FWqZME71BhgFDhrm3Xmi8RjyFHkt63ZwJ7BII/sEDrEjChXei7Cri0RCdo3WFY6YJer6pJe1XmLPV69cCxQCShvCaTjWJxNSPVWwFSWLk9JbBz2Fvm+ctKKRyLgOQrOs3YFGGznX5i6vP1/RvjHcuaTc2iQ/hdQNKyUQ+NSoQkjZ4VzEFOTkKt2WYFa+NcRap6OuhzgeeXQVdl71RggYkEqxXUh0b8t3Tq+rhuq9F104O6jBuM2hLfFsrhXSZ6aA+dpgqacf+nBPm63E0hH2nZjaB4AwXrQZaO","layer_level":1},{"id":"74304c2d-414f-40ca-9155-fde8c06a0128","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"配置文件详解","description":"configuration-file","prompt":"深入解析app.conf配置文件的结构和各个配置项的含义。按配置区块组织文档:[appname]定义应用名称;[httpport]设置HTTP监听端口;[logs]配置日志级别(0-7)、保存路径、分离日志类型和最大保存天数;[mysql]配置数据库连接参数(主机、端口、用户、密码、数据库名);[redis]配置Redis连接信息;[mq]配置消息队列(RabbitMQ)连接;[proxy]配置代理池;以及其他第三方服务如[mf]、[appleCard]、[jdCard]等的API端点和回调地址。重点解释proxyUrl环境变量如何与配置文件配合使用,以及proxies数组的用途。提供生产环境和测试环境的配置对比示例,并说明每个配置项对系统行为的影响。","parent_id":"53d903ba-6508-45b8-b48b-b3d00d3ed07a","order":1,"progress_status":"completed","dependent_files":"conf/app.conf","gmt_create":"2025-10-08T20:05:30.6781661+08:00","gmt_modified":"2025-10-08T20:12:50.0934672+08:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllJun+r82/Gu9h3dr/sudqytlxed4ZV2GKW8hZ0wjnzMJzy4Ohac8ZrkcdbvmLBCy5pE4xUQtFA8hhYdASDqIm10S+PIvKQH44q4KE7YDIXlxN+Acq7MqcTsSjuNjeUEkgudrHx71A/9jkorJHrJlsyk8H8HjNTx3B1fpnTr5dF9AXC2SCUuPtV4IcdofxKTF4Gzt40qxijK/KYQcgiGjoRiS7WtQpx4nokpBQz07b9XY5gdz4j9eb9neooDBe9yFf1110iUaYj0+vO6RdE8Vc7N6KPr0SmPzsdsEIpnlQqnGUTVcq1qqC/mJ0Kf0gBXlEUebNnVpnnvEc3GxiJqtZJf9EvVl8seqK+82dysxvzSO1gjCUdHRDLMtzWy19xmQheL6d1rw6/pW9xbTeExKDmSgJtourqUQe+4qd12Sr/gk9n3h3YyD1EkUl0HpSotdWFtuuZMkJSykI5od77zZVFuYOX4ifOj7091oQgXQxnPdW8FH+GSbp6oEkj28b5Ix125J0z13DGG64dYldw9Pigo2PDxfajiV1TxLK/f55+ZEhAbfYRbeNRsWQb6B1lGln9nJcX4aWwl1wy7ZrPkIifZXW1ststtxYJvYM69iPobCB08/NlwAXpWKKC7qdHw5Uhy6ktHuLf/gq1rGn/qgkMrntoeBcX3jl+VKYdZel24K8tf+28bPgcxCT2WK++j5aL7IGfIqFoBzjri4XL6aFrQ7t90Ptm18jI1aCNovNO9Rih4olxoov3po9qJT7buzqReW8XcLGy8c1h0ab9RAhQJEWZXwTpwmdoc25WokOr9YDQnabpmcYjemIX9JL9rp6VB648dKDhZC5pP/ISNvYpICKz2qDOtmN3mbAE3x8AYIkJCu3QtCD+Kot9dQVbIkddGIGEr9jd933I4zQMUNDW9rXoojIvcFmmo2Qk9V/n9sD6mCYZAL6X9ntdh8YXqWA9oRmixIQVKdIxPDxrvpn3yKWI1Vmnx01Ez14hN9mIRs3ffyJbnQ8MwI1msWueCyLvYvXMHzTcockWRjnR/GmQ86mSvM/cgXfaEBmRZooGZqeNyKse5LMOZutjImuy47ONdYYccnj/L9qDyMyJjBN3bFs+BUItf8RKVHWhPwhcRyBQ1kwYSxU2yR+N8kyohkT1042nQQfOzDboweuTgAqpTjf5pEYXyPWoELgYz/AHJNVTlRTe1mdBgfgbcsa5MsRjuBTJNhQFIJZAdGZUXJ4uzZi12eA8cxqt1UXGBUAClmXP4gxOf/8rArpxcYDG9p49F4xyT18lVE/lZr1gqsg14=","layer_level":1},{"id":"0d7875e0-1107-4966-8a99-a6d24685c88c","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"供应商集成架构","description":"supplier-integration-architecture","prompt":"详细阐述基于PayInterface接口的供应商集成架构设计。分析supplier_interface.go中定义的Scan、PayNotify、PayQuery等方法如何为不同第三方支付渠道(如爱博、京东卡、天猫游戏、沃尔玛)提供统一的接入标准。结合具体实现文件(aibo.go, jd.go等),说明各供应商适配器如何继承web.Controller并实现接口方法,处理特定渠道的认证、请求构造、响应解析和错误映射。文档应包含接口驱动设计的优势分析,如可扩展性、可维护性和测试便利性。提供类图展示PayInterface与各具体供应商实现之间的关系,并给出新增支付渠道的标准步骤指南,包括注册机制(GetPaySupplierByCode)和依赖注入方式。","parent_id":"1ccdc69d-fc3b-4d08-9be6-169095e4a163","order":1,"progress_status":"completed","dependent_files":"internal/service/supplier/supplier_interface.go,internal/service/supplier/third_party/aibo.go,internal/service/supplier/third_party/jd.go,internal/service/supplier/third_party/t_mall_game.go,internal/service/supplier/third_party/walmart.go","gmt_create":"2025-10-08T20:05:33.9890818+08:00","gmt_modified":"2025-10-08T20:13:46.8772551+08:00","raw_data":"WikiEncrypted:ywogS1mtCJIl+oV7mNfjwDV4dOWErrIfn5VN3rZcU5zIjilGDlComIcwwDZI+34gNPPMwtnac1GAjEMjy0hC9xOCYI0xdruHOD03uXFp8XIAWIsegStP4REGBbmH/L/wOeeiS7zf6B3e5QmC0ktLhYk7pqjh6FOf3uvPyT8dOTMgwUS1OA2I+riym/9wqDYEFak/Xwdept3NvSE+SVNKbk3Hxi5b3/MFw5MJF6gdAJr5++Liy1daocRXXIW5Ym0ZW+qUvP/VSGh0tFuJLpKHVbWhBKrRPXQUHcfYrn8knJomzT/926tME4M+ao+tDaMDYifqELysn0AP5+zUmRZOl4KXUi0ZUk1GOGV0Sh2xJv78e4zm8P7QflCuLHtfsO+TX1Nc9Af55DpLU+7SWk1/e97KAcOgWYcKEBVHriAxnzKf9yy0Nm9hz5lBDc5jHqKcjXCuPMv65Pyw8+UnkFs6X8sv38bvLGtOTmYqFuNPYYZygIfw5UyRI13n1iuVjmXwKzwjZoyXc0MjmbtRcYxUaePR+0d0BNLaauVLEOWhmJplKsyeCJvtyMkovdSMxYmwnvwIEP9kKrRrL1Pm5Z2Vh4ePOy0VWaFyF5J87jPJPDBkQIAXn/hIXtcD6wbpeiTBLOxud+M2NWa6ZizcNl4Zef+YpzDr2niKho+8DQYZpXFgtNmRj7cM9nOVr0wj9YrIKvj9tpMixjz+51oMV26/G5gZjwoPl/WBK1sQOp0FIKI5vRWxntVoSgQTsrG0xjV1OUbSanOjvbfWFH3YEm7GO90orxnnDt9ujvVVs2oTpjnFzU5a+s3DRl6TxrUJe6cvO6OucFGzSIdG0YX2pL0205LtIwO+wGt8FUxF/5JWnt+Qw0xIO2bLNc4N0zfRmXmMaRkRF72+CuFlGhDaemazh1OM6R6697DnAolV/r99+iSJJrHoiY0qY8sZjWn48waBYPNpWJ+VaW6TZ7lb8+4Af6SkZu3S8jpH0pscQ2KTpq8pMJBoafKxhn0dIfxCHve5a96Ly9PUuF2JYqfRXZolmEL6GColhmUEI3uKRS/XYIGZJyzXgqpVQOskgU7kuoamNye15tCbrs+fqNcM5+XgdgnARMm/1ck0khmOIhg37hY6kFW0cuyl3yth2hsIPPcql9z+Frr/Zmd/Y6aQg2cWYKCUt5CoO00JSsdiqAn3uMcVuG+I50LdrabWjYkV2xRTagO5libnh4qvDutNVYO3ruMgAN1J55kUAaghK9YYhgcw0nAbSz2HC0U+B+1iAemccnEZFSw3iaUrSgV8BOBIbU0C6FxbELNPsxgl7slaQUFZtfK7kwGKfjlrd8HNmx+3Eqs4AG9sgQvAmjgoEOxY+EJri8lY7g9Ut6rHKaaMUivhywpPo41n/b0ZtfE8N1FGgxTnJ4MCvN3q5cOWsdt1GGqEoOyHbUeodHF4oK+9iMHEse9R6Pka58yV9rAJbM2PloCqk+vyeRjmKYm17KLCN9aJ2L8gwM6XcD5AGzjApqF+OKzCNgJTdl7a+rv94Bw1+scEF56CDhldSoDOI4S6+qdIUN6A7RS9xst7LQaGbwOOXHWzxYOa9IKvgG9k41DtMTF3ItGD6Ra6Pfd2CJfhrCjDW+rClHvmdVy8ArCx9QvU9hUxjxM4oZPpy7B8sWRCF2EgVGwzAAX/U8qOdxw+6Vsy8PzbbhGNmDSRazuAj++0151QsIdXENeoMfScdnGXJOVdTCnUibQs7fYabLmVdMz6PvliOmUuK6dwwdk+0+8=","layer_level":1},{"id":"7f560146-d4af-4131-8722-dcf698604b6f","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"Redis缓存系统","description":"cache-redis","prompt":"深入解析Redis在系统中的双重角色实现。详细说明internal/cache/redis.go中Start()函数的单例初始化流程,包括sync.OnceFunc的线程安全控制、从配置中心获取Redis连接参数(host、password、db)以及NewRedisClient的创建过程。阐述Redis作为分布式缓存层在高频数据访问场景下的应用,如订单状态缓存和商户配置缓存。同时分析其在代理池管理中的状态存储作用,特别是与internal/utils/proxy_pool.go的交互机制。涵盖键值设计规范、连接池配置、序列化策略、缓存穿透/击穿防护措施及监控指标采集方法。","parent_id":"715db9db-8d32-4ea3-926a-b56c98ea6d8d","order":1,"progress_status":"completed","dependent_files":"internal/cache/redis.go,internal/utils/proxy_pool.go,internal/config/cfg_model.go","gmt_create":"2025-10-08T20:05:42.1421683+08:00","gmt_modified":"2025-10-08T20:16:35.7591809+08:00","raw_data":"WikiEncrypted:dAMSC70bWva9SabC1uic9nJyKwHAU6Vz8XMWhQC2fsd8tVyLbBciJVXYmCmH1Ok5kX4CcQ9stt08MrQ5/ThRrDM+v2SCPpgp4Rafg5KxCF1fPFNDVXxBNZ37GptrzzjgJM99R8q30+ZFLv7KbXkbAKxbkockVkEmL47IPcaTB4KQGIl0uH4TX/HF3pCq+S3Q0tuB3eZC8bjsqKbl+5IeedWG0KIv8rFAUZVgH4KsudB2nCjhiO3iDTBbJyJJzIIaAoUxJ13ZZxE8IkdiBjnXKUhU1G5hxsgzCWvPHro84xG/PVWtn3FZMJqD0/3W8md05WDT9/bQ5O3WpeJhB0MvWfiTpiEb0q+TfDOQ5ufOTDYYs8OFevJ474yZzjDzEhlreY0GCRgXFXEspvBOK/kR0XCzGg0QBu6FsrdoB62vcRXCuFm0Yu+LmESviXgzWmNL/LQj2W/kfb/vzTzDWW7KTua5QJwKc7IjgEnQGpytTI+uAfWogK6x4LuoDm5XIH8Z2pIMu5FaNwEJfzRh3ug1xk86qdhb5TGnCN1w/NhiNkHczNnPwOaQB6VwWPyO9ehVfKsPHQyTqOFEXvxqhciy6iECEBiiyl/c4/0S3b3FPa6NtujCxQY/nb1+6GGOLECBttFp37DHzKsXOV439jZuHxLSUpyy1wgWpfEipayjIffK9qKXW6B4hQ1kAr6GSh6vgkAgn/K+wt8nlC/JO1hD0lbENKKKhkjUM+eXCgWvNtS2Kh4ThFs2ZUr0mB0o9jmwXhxUHQf0INId/Bw0WnJZsJnjWd7/cu76sNJBwClXzo1uYZaQirUv5iizms72L+OvjjL8UKmcMHzuYgSTqs5D0sBYvU4ppkVH3m81hFft69rcUXad5E2A+kOwOvaVAUjC8J8n5mWX/g0kF/BAriXvWldXEKG8NsUT1zo/y2xHvBUltzD/9Op7yZpXpCvVi8nQ/1T38xUFCvXd3z9knvnC8uQCdAWfx1PW2Pc81yF45Ca6vVg6B+xeDb71DBS4G6YbqgHNsZIlddGgdN8FvJVYp6VzMi4kJsWv149tr38aItNf6SaJC4rGMHRwKRPSybHJLSfkNeL6kLfjEfmI2AYWjiuiVroia+ccXaO2TjmFvx73cid8zpvqgpzGjczGQ+zHLjP3na3Zn1HPfrH5BzqcVmPNfXrZF65n6PXweEBiv2at0XuXVgabpbjNq4LJ7sHQqECC0opsyBcQKaAFNJSEnj5/mdsklemuJDCc5yxxnXDDNKZj3H8A0EcVwrcsKTHdHpqztexy5yT+EvtAUpvd8A==","layer_level":2},{"id":"b99f6bc9-1a5f-4e15-82c4-3f4c27eb0724","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"HTTP中间件集成","description":"opentelemetry-tracing-middleware","prompt":"详细说明 OpenTelemetry 中间件如何在 Beego 框架中实现全链路追踪。解释 Middleware 函数如何作为 Beego 的 FilterFunc 注入请求处理链,在请求开始时从 HeaderCarrier 提取上游 trace context,并创建新的 Server Span。描述所添加的关键属性,包括 HTTP 方法、URL、状态码、响应大小、持续时间以及客户端 IP 等监控指标。重点分析熔断器(circuitBreaker)的保护机制:当追踪系统异常时,如何捕获错误并降级,确保不影响核心业务流程。阐述 defer 函数中如何记录 panic 并实现优雅降级返回 500 错误,同时确保 Span 能够正确结束。提供中间件性能影响的评估和优化建议。","parent_id":"fd2a2cba-0887-44b8-93c2-9cc9e520daae","order":1,"progress_status":"completed","dependent_files":"internal/otelTrace/middleware.go,internal/otelTrace/consts.go","gmt_create":"2025-10-08T20:05:46.2609179+08:00","gmt_modified":"2025-10-08T20:16:57.8793561+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoD6zEjjF6IpmyNitJcpys34AnG6PRG58wTvBVd5Pmm2kROkOC3nqxrdiJia2ZwW+aVBJ5JJGiU4dkXutD2rh+bzlkJC8jWdsGWSaQ5H2oLCwG1vWwVltRVMhJIeWC+HkOIszmF8dq+A2Dcs3KcbVKyNI2LkVVZxJKR24qDp6pYAy6UD5rjK0NkDibKdCG97UReRwNhjxHVv3yuWh71x2xGK30jd30THXNZllSVK/mq1Q0wR67edEGouF2Qq1FaFMoPk0c4/4scaTr9j3VhDDStjmQocADwqWA1f2BaiugKC18o7toK/YUt6rFI0OTsEIjPrBWrhHyigzdgMLv/DPCVQeqykA+MGwtdH5xDA7fov3VKZ/g/EU5+qGLV6lHmRTZxgX0xfVUxIC5/mRjWpmx4Ea6BGVQoGchl83b+jQVflxRo8OsHEnHhvKAc4Fy98Kr3CAczCWk+RbjHZ4vxJ+zX2fso5oEFoHDVCbHLxmoTwY7L30k3cnaRRs4nbV+q5dR1hnR1rUkuLWp6dGEyazX5pclE53oHUC3C24bUznMrjadu/OTBfPQRWkJ+oTah8/sfqkDXDMQHIZr15mnmEmHIqm8U8FfFJYvlpe8/x6yUmjnsZHLapzkozleobu1ctPtRnCajlLG+KxR+Tuhogz3ZmAQMVK/oUbQOsREmhQ3V5OEXbgVR5tGHE4ECXXPyjbCE9qYa9F4DoKy4lXKYtMgJqxoNSptSO8Y805S43oqbpFRQcQ/1ZQB7/h5mpgkGLLAIA/sTqUZb48tY51biZh52YtaWPfON8z53Ygv/VER+xTHL10Dvo7iuHl8lv/Oe0j2RTnCSyEbXmRNlyo7yJhN/URs9fkzeyfxx/zD+htV+7bBea882sDmhQ5YOK/K9t6noEg9jnDs9SKto4x+dSCscWRSzWRxoaNLyqlQDxYg7NUBTxLtKTFwVoFqmrLnNkt7gtmXaEkZYTBQu2r8GV7SeblWXIjkCdneenxalzaJSVMhqqWniDt6zTWUEo89cFw22957WTqq3rxOfrGpUu2Lu6Bp9iedb8hz62VRPfcijqCJdAp1uuxP2XH5MPnp/jkRc/SfAJoUVdA/dWH3vWBxLlibKpMkEtgzx4ycF2CLy5l5U2GnX2QjECByFOAfRibSQV7fwWQjGPr+sJVLzql3c1DrR3TwfpCxT7/Qcply20ElP8wHel+1rxmvvRhuogQwtKozN+LI/DedE0fZc22ws1bM4gALZmmc/YUMY5hUGgyT//b5ObXlnRoX58terCMfojZ9e9fdXXlP0Cn6Ir4ZH+cJR238qrbArW0cReXD387k7xiLlV++REBpyqgCAg85KT7NPgVp0ibNSBiiGSrhpkYA9V6spiI1gnMGYUIxkFjkneCevCZ1WLIX6cBHf3UP1hb6KjvDfc2zRYl405W471","layer_level":2},{"id":"00f89107-2ade-477a-b10e-0c444161fdbb","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"资源标识与上下文配置","description":"opentelemetry-tracing-resource","prompt":"全面阐述 kami_gateway 中 OpenTelemetry 资源(Resource)对象的构建过程。详细解释 resource.New 函数如何通过 attribute.String 设置关键属性,包括 'library.language' 标识 Go 语言运行时、'service.name' 定义服务名称以及 'deployment.environment' 从环境变量 ENVIRONMENT 读取部署环境(默认 production)。说明这些元数据在分布式追踪系统中的作用,如服务发现、监控聚合和链路过滤。结合 InitTracer 函数上下文,描述资源对象如何与 TracerProvider、MeterProvider 和 LoggerProvider 共享,确保追踪、指标和日志三者具备一致的上下文标识,实现可观测性数据的关联分析。","parent_id":"0ebb9117-99a5-4092-862c-49ee70ccfee0","order":1,"progress_status":"completed","dependent_files":"internal/otelTrace/init.go","gmt_create":"2025-10-08T20:06:11.5699417+08:00","gmt_modified":"2025-10-08T20:17:55.1134883+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoBSpNXDbJChStEUz/jhm68zL/ANbfI/y2zT7x32t0Vfi0LRsC2xXbr2+POukHA0Kcq2TwfJsDhWBc8H9vZOt0nttf5SDMxFzrKu6uJgupH45V7WOr6tInJYt7lZuWEnewpt+1EBpgzYQa0MnJlDYouRumuBtY7TU8mZlpeNKQJtJxIvjTEod/yQ1ijfeUuDTEMGAUs7QlYvSMuq4+AChv8cmeelrSwuzAiPSRVGISXYRRVldgYZPN0HssWAwGoyQHyDZfCc5jiTjljSgHWcbUBZE/UlRUddSKB+mSJz0guHY9Z0cPS4NTZZxPPOTa8RzsB5SXRpx5sZDD1BHEODvjd9+k2dmgdu+xdAiX/xF1IVJ0exCGkPVXC84MMiFLhUsJpNMx6sj2YBQGhUaETnTHSu4kJYVtBme5SdF6NcMlwe/WkyPANWF/qB+l4miChK/lUX46paZNBdXNsHu48SaZXvLJl7hriSOPaSsPgg8hwNaOt7EVNDILcu2xGQanYTbCjeLGyMU+lVOoWt3bvjYH1iujWYhoPaPLLMbUCNpbizNwaTds0BP9kBIvFRwKP1fzJum1Qg7tCdrSzjJ93dpGVEL5ZD3H/zvBbaBQGyJ6lQJyO9tz2uhU7LY+FiR/NfphGK8PXbi/oCf1hLxfamcI71qTluts/GIVM8XbbNM3++jiwqas9YPQCoQam/lismditjBck1KBcn51e2XbcrDkGwegBXbxkn4DnkyXfJp0IHJR6kdUqAs4bA0U1mUshcfN+D4qTtwicGD0ktJFVNzOOJDg7x8iocGq2eIUPA3M4qr6MZQwWerxlrB2auVEJ8HrVR4C4C/W8mQZd1uXr2JKNbsYipKPxqYldmDy7sIV0CJsMCUSkZuQZFlQDRtJ8ZxJsG5y/k3e1q2m20Z1feFq6rvmc3PTZQ8281/LRvfhC8OJK7AMtTG3TuNkvdf9JKu421O5JtczoDq1RJzdrX/yMJtRr5+xYJMj6udeUBuCPKIdluPHJzXnfJwHirZLhDQE4/ALS4d1ZIhe/uROQvbmfzVSRb9H/YZxZOeUFLaMREAuzuvAvZGgcX153m+SuXbx0cONwtBW8xTK7SBNFJ2D0Wle6aLHeu03OGwqnWiY4AtfLspvKMEKE/0uE4pwj+VyBjUMHFqL0m8m3ppXIOaO0uyEDSdwqQ9V3gu6TGpRUswGUMppuUfm3F0Y/WX/XtprlIOjPHEg6SOATvlBJlvvDsbO/94wrLc4MaKIp4JOujaQ==","layer_level":3},{"id":"80fb1e42-5bd2-4870-8b88-77d31ff5c478","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"API参考","description":"api-reference","prompt":"为kami_gateway的API端点创建完整的参考文档。根据router.go中的路由定义,系统地记录所有公开的RESTful API。对于每个API组(如/gateway/scan, /gateway/merchant/query, 代付接口),详细说明HTTP方法、URL模式、请求头(特别是认证和签名机制)、请求体schema(引用internal/schema/request中的定义)和响应体schema(引用internal/schema/response)。重点描述支付下单、订单查询和回调通知这三个核心流程的API。文档应包含实际的JSON请求/响应示例,解释关键字段的含义和可能的取值。同时,说明API的认证方式(如sign_verify.go中实现的签名验证)和安全要求。提供客户端调用这些API的代码示例,并指出常见的错误码及其解决方案。","order":2,"progress_status":"completed","dependent_files":"internal/routers/router.go,internal/controllers/scan_controller.go,internal/controllers/order_controller.go,internal/controllers/payfor_controller.go","gmt_create":"2025-10-08T20:04:49.3906967+08:00","gmt_modified":"2025-10-08T20:07:10.9661719+08:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPkUytUlTK+XtmhJqDmkbtEHUInBMyGJmK+1OrYyJNWBIpK5MqFOE4zxWbADYMfqE5uPRF/+D2A1GFKxzslzIffU2ED8IRvJhimcsWXs7V10I3YbNlFyQ3JouxPFe7AzJUW8ZSTDXNZQ2liDrzTN77VbKrrQBYsfAGuS7PjO7E+mjbY3f52UeUhXzrWUYj/QANNe69UbPejykm7kMXkNLU8irJ2a2Ob+Z3TTi3d9jPEbDzGHwMdMC7Tp7iimiDBX8+UCUjmbbJChUCw8jQRSiEGibbN5g1VSyzv9cLGWsi9hJxL6hxjG/FJrQH4sOME/m5ZzUnzRB0+I3+5cWyOQBl5O7yFLgn52QKOR7/UxYEWZ8uaBBEfsHaDUcVrX6jPmUqKtKoWb+KFH8ht4ElkjHdEbSEYZ1v0XfVXD8z7Xoal/GPY/UEFCOTaSAu5S1cv4ZLSVExMTk6HI0A1HIuTwjXxHDxRggvOKxEwyWXlCSvParfwK/ro1QFGt1BFE9dULPHDqS7XcJglmjH2yJmvO+i/7gJmAD6ycpIOBw6duQW5la7IdQtMcxAWemBZwhfisVKCWq1w7Yi+f1iO89M2hGjZTxR18wEVtbAGqJzARA7ixJr8gzjjjvoEUDCS1DdrVTomxE0/PEQtLnvp3kkKR/4oH055vAZmLkm4w1HWCJ2uu+593tmRfOPXk3UAklo+4XG+w02eJQhhlWwvxeJx6y8UyFZeea5VazybqnCajdRHj1ZU5MP2VjdOKAakPBuL3i0FIcvn6sPhHYa6N5w6M6306KBA259KDDzwJeZ6/9lYOzWM+ahsHOfJoNyLu4ONthaoeFh7N6TWKJBsoemN/6wVS3TQiZnWZGFHSpf41naMpLlt2PokBkmDY/6mPj30H25PydZDzG7WehjjZm2ovYhbFXJweQd1Fb2hV1JRjZC8+DcsY5DnZqf12yOSLglqJquU0tS6O7pKtN40WLYyI85QMHQIbpFZVW9fEnOUNj3yjJBxXbzhZLgiUyLLhSJIdN1m0ENI8xotulQ3+GJawV5IfqTCMvOvPkTF9zY77r6hkLqeu1SMEUWjMiKB1Jej0hWJmK1f93krh5tvxqqS44tAON3nsntP/Pxr2pS88IcBquUcNq9ooNrX8A0HQ5UfF56By68H3r6jW0xxTGCmLB9hwz3rynLNGR1D56H4PHB7+Swy9AiXR1ZVYNDk3ggfjFpRT2Yp1VNuhCLq1j4g2B5tWqY+kUfDwIYjlFVPsgkgCJ8Q6vtXQ2pVNY4iCW2EzD00rqQkxHwFVM3trdhemLmzs74kdOp2TaIiU1ChwW3okbHdoFXvIXkvcPDF+UWbhGj03XKQsKMaG7vEozDZLF3DRRVCWNacy6bG+vlmpa+uhgrUVvDg9OYhuZbOQgAG6PFpNfeFmoftHn24ctqkfTrzjFAZCzs2xk5RbYibRu1TXTQled6EdXsS64diVD7KmW3T3HPWTTzavVWnqYxu7rS73JQ2fvQrM+juTZG9+HqQv/4BjSmUtT4Al9lWtV+/vy235vXV5WhpyrqmRalCcTCpOQwAX0ydpdqumKP5ju25UQRG/Da0pswtJF90T67Z5SXg="},{"id":"316c7f5b-5e53-4322-9376-f94f1cc1ba37","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"账户与代理商模型","description":"account-agent-model","prompt":"创建账户与代理商模型的综合文档,重点分析account.go中的Account结构体及其与agent_profit.go的联动机制。详细描述账户模型中的资金字段(如Balance、FrozenAmount)、状态管理以及账户历史记录(account_history_info)的审计作用。阐明代理商(agent_info)与商户账户之间的层级关系,解释代理商利润(agent_profit)的计算逻辑和数据更新时机。文档需说明资金流水的记录方式,确保每一笔订单结算都能追溯到代理商的利润分配。提供账户余额更新的原子性操作示例,防止并发场景下的超卖问题。同时,讨论账户安全机制,如登录密码的存储加密、多因素认证的扩展可能性,并描述代理商分润的定时结算任务与数据模型的交互流程。","parent_id":"a5d56738-c20f-4178-9f81-d01bb592f194","order":2,"progress_status":"completed","dependent_files":"internal/models/accounts/account.go,internal/models/accounts/account_history_info.go,internal/models/agent/agent_info.go,internal/models/agent/agent_profit.go","gmt_create":"2025-10-08T20:05:09.9169119+08:00","gmt_modified":"2025-10-08T20:13:19.8865856+08:00","raw_data":"WikiEncrypted:3dIsHCE5EGeVKP2C6D6lOG7DpzlCciGgDXyeuMbTmE1WIYUNyK5FOTQ08pifOdb7S06M4Jo37b31e6e6KBgDHtoKWhfRqraUCev6GkQofWmjG+gbsxrjgnWOEtBWJHH2mK0i/k97HyaF8t547pERtkVpDZ0SrWobEEXkgbnva+o5TnBqNEE2isQ6owUZ9bqDyEcspoX6lfqL8WkdbdEfW8dmuISRiPXhe4u5Bh/C5gScPFPoAgE23w/SY3esazX32NbwNQHbJkywtNQxUigGC1/ZijRyuYFc4ENJ2WOHIAfA0kzHWGjSqw4RvJswc0wwMSoBmXDrANvc8wYgfeTH/GsnSn9RWooFcrtsv+YbTMfIAJa+u2i9sIwGbO1rhT4CiXFMiW3MVIC4NdG1HIllf9r30a4nDqHC2lIWylH7XPTXqPlo7rvfEz7p5MIJHzbZ1Zo6SyEhNbNl6TlH19zE/vyDYWSKN06L/XVZjlztE3YFFeawngMD+b5RnhheyCeeJLO8uf/gKIGD4jWkABkswIn10pWlGXRXfVXacTucUIS0st4A1WAQ1xwC6G5JWxSaqZJtj3g4bLY2e6+Sc8Am5lT7+VI149sGR/QNkw5HuC2jwM8RRdHPpyze3l7pHyk0D8B5rKcrDUUUXu8QKxCIPcGpNAEpPCE49uXRu/N9KLlmQESzdOusKLhQiXG9jK0NLhRlioTNTjtWP6Ejynav+kb/361mvzJy4SdVg9OR3/WrKmiN6Bb9Si8wiwvwcQdetChmX83aYfQKUJG7jEvKLj/pvcom+bo2qwTAFB9OlbnrIyVb0h2gEWufO3lfhdrYPk5UJRxJgMp3LZ3TpTEo9dN41w7aVTpt8OMT39nnkDk6lC6wNbtmJgZglz5QdvR+VusHQWtiJeGX92Lp8gZQr7ttZMH7VrMxdfY79BElST9D0EqxgM6MusjG14/uUYkXBlVil/iRlPySO1bdZBIB/Rj+DOtJDB5nk3Ev2EF3xUSjnm9fQRtbnyBcAvJg/uCXeQhMXEAbr4575f61JSYMoD614GS0JapQh3wucuBP2bBjP+Sidcho9gx7/5t9Ir0in5DxXivTVKPP40R2/ttNUPfIjlZXhdUXLXvll52WQ+7DcB+ecSDHHrYrlx/HRr1lPcUdokdfD/FKrXRTNIehSK9lvTiTXM0W6VYm/dzh5RVllsWVCZ5rAX/r+SLfy0UGYdYAivEY3KK1Jy8ieXqbFLrJxr4Gt9f2FEhjZSeKYbOQGWl66/GSS/wQErqz2YK8KWl2JwhrOupYjU6lJ9C8/aq0x8ITEbScXODqNs5eElI/oBldfFih3MDWuMU98pS/DpTTAFZJEKnAYvY4MpfPZ89ZvsVvoVNZ5SQt0CG15NZhDXFa3eIAAOhdRfPbE5zj9X2gGj4vW6EKzc+6AYkQDNLyIt6cKkNrYrVSeGZ2x8GwSYD2bPvzs0bRM0OMhse4wdLhW0EDOwKPrdd5UGagc3XOhbzINiAd5rnRpuad71eCnpy8geDUkX/XDVB9gIq65XyuG2kgwBZXMIXUorWPr9BfH5kZ4wWLV8HgNTpCXzJ6GsX+DAg4EIx3np+xGDRKNuJ2zY4U+aCLlIzJ0NZXspiDSfrA0fQW6Tn8SmMsua8s2ZK1VvkQfCvsCtlSD59dexHjZ9Oc1mGY/bL8gOyvkf5ljnfEnK4xsSQHTeWdD54=","layer_level":1},{"id":"715db9db-8d32-4ea3-926a-b56c98ea6d8d","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"数据库与缓存系统","description":"database-cache","prompt":"全面介绍项目中的数据持久化与缓存架构。详细说明 MySQL 数据库通过 github.com/go-sql-driver/mysql 驱动与 Beego ORM 的集成方式,包括模型定义(models/ 目录下各实体)、自动迁移机制和事务处理模式。阐述 Redis 在系统中的双重角色:作为 internal/cache 的分布式缓存层用于高频数据读取,以及作为 internal/utils/proxy_pool.go 中代理池的状态存储。解释 cache.Start() 的初始化流程、连接池配置和键值设计规范。分析数据库连接管理、缓存穿透/击穿应对策略及性能监控指标。","parent_id":"576b2803-bcc0-4769-89b3-54c89e6b7381","order":2,"progress_status":"completed","dependent_files":"main.go,internal/cache/redis.go,internal/models/init.go,go.mod","gmt_create":"2025-10-08T20:05:11.0790017+08:00","gmt_modified":"2025-10-08T20:14:05.0406994+08:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkE+olzqNtNUVmkVTDuTHLlK0F25dp8+akt0Je+bfNZcjdOyycHvaSL/ZfcM7nhd27KKoYh51tjBGZdcGx/3FA7Hfs2MZ7KyzDPsgFevcdKUyGudiSk5WvcEdsfE3v4x9cKcsuC3LtYTT3Kmf7W7y4s0/79F9Lm08KCuSa3czoNos9iLbUwx99A3E8/cfoNA6cjQm7bD5GuiybQOvo6dd1OGe565/6CYmgqZp8cetjqf4FdAzQRRMSB9NMDn41crnsBB5oYmClrq40pXIGfimq50WTVhBKlmCh4vUOAqlOWKRp6MhH0/GlM66DwizL/Bbzxmzpj24bgFvmt1Tp9F7tvJPJz9aCZYxN13vd7nMHdMTEP+n85SUjlaTqJLhqc1giZJL6Cy6aM8146XjWdaBUEq5bbriHD2HEyMRdswFeik4J/z8LhkADRaB/484L90EkotBnzh2+EKyoxWOhqbrsGKvSOK+FEK4SWiyDuH8vVYMzlr26yLhfwRVVhkpLl4zwM6ygOrOSyfq66EjLeKWHrxrqEx0MkSmHJdGktvXHWlYg52qy4sWnUCsqfYBXoxmRTdbFJaUSUWrgy12TVpkzTp5Rv3vxL731TDYAqRZhSgqAk2Li0j1LImW91iOrx4/wLe0VhjnbBmwoRyyG7wY5rJgcCE/k9jTlYxnwLGbabEJtiYD40hMaKLEgtmHrB2cO9dcbcAxlCuPJdkT5h1S+p2HBTZ7E4ns0qZwpZNxIan4mD9H1eJl+2cPO6RuSJGfL4oeZsYwNuaPV5msTWxHP7XY4JARUWrJwGGV6Ox03hbfhljuo99sogQab+3fmQqiTaXbIT/X59QtUB/L7E2Q9z5vyCF6Zf4ucb+GzORPQP5Ia4GQ3iNvK1v4HVHVylQlCIrGPw0FPfG924nbT/OzRccT6IS/FnAIffeLxqaM9vKtGIfIJ1wxYTheyIZrNS71YFQEVVvaZHr3he2yxJlfEK8OLaU/IX98STayQsVO/F6Ee2Nz42w/IDINAYHSUPcaBEOiVZ0Y0lZAo4F+5tNnWwSCDJ8GbNMRyzPFKEcORapvkWbxLJ3lQmEZZVRshT2Tobl2az2fu8c8Z0/5KEq7It8VgrHiRmhsuGi2Ya4ScGoPP1BsJxaJLW6/c5OJTGSPoBQQ8vJ19C23ZDmCHEQuA25fnAfk6azkg+Z8RQ5kezP0","layer_level":1},{"id":"8600f0c5-e3cf-489b-a029-725506750564","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"代付API","description":"payfor-api","prompt":"为kami_gateway的代付功能创建API文档,尽管相关控制器代码被注释,但仍需基于现有代码结构和命名约定进行文档化。详细说明代付API的设计意图和预期功能,包括/payfor(接收代付请求)、/payfor/query(代付结果查询)、/balance(余额查询)和/solve/payfor/result(手动处理代付结果)等端点。解释代付流程中的关键参数:merchantKey、realname、cardNo、amount和merchantOrderId。描述代付请求的签名验证机制和参数校验逻辑。说明代付结果查询和余额查询的实现方式,以及如何通过SolvePayForResult接口手动修正代付结果。即使功能未启用,也应记录其设计架构和与其他模块(如pay_for服务)的集成方式。","parent_id":"80fb1e42-5bd2-4870-8b88-77d31ff5c478","order":2,"progress_status":"completed","dependent_files":"internal/controllers/payfor_controller.go,internal/routers/router.go,internal/service/pay_for/payfor_service.go,internal/models/payfor/payfor_info.go","gmt_create":"2025-10-08T20:05:17.6767438+08:00","gmt_modified":"2025-10-08T20:14:21.0206729+08:00","raw_data":"WikiEncrypted:55P/Wp5RCBekgVSchCI0/7FGaz8xEKK0/uXAbqNq1zF39eqFnNyeeqx4SuTTyjxrkY2RVGC3L0lJkUZ7WH789Y1JfX9nf/LLr7Snb++KDdJUd2zwoEwu9KvRNoPXV2rgj5OPIVd0VZrI9B0xMfEl5+NlyczbNJwz1SIFUX+GOECGQB0mcK0+GwPROqmXYrSBDHXGJOKTfZWWX2gk46tV1xPr1Cz908j9K9ndzSzcTbPnKKZ8cX3dJ+d96NDY3aJk8TZTFxDJX+5Si2n0rk5URpXC9I6NHm5IHuXUsBDrPmkP9EtX6PdLrYCK0vI1UxgadQqysmIgSDJxbDfO3FecJuqdiS/7aqLbuAare46je6Yak20OROHkVjoPseFMOluzDSieu6pbXhX2VtT6ftAxN4vOrGThVyX5Cj1jsIml67WqSmpMQGOUcZ3oHb8cz1/sEDBMd5DgyMIdFNtai9sRhfuY4Psmrk7HmOiA+j40X40lmDigBhp9r8YmwLrIWsWpqArs8p/9LsTDkbmDvioMtLfCB/dZu8qIQYalHW7EtL9mzCGjLXhvRIvYnBKTDU2BisH38K2vI4wMFT+Xkv8MdxW4Oaiq3EXNQ3CsabEiNRMMjuv/gsM1cek6VRxU06et6uACCRUlRAS+np0FrMU2NLihsccYAZGNxdFxr375EKw5Ys7IvuBb84hz5sOxADZzYiUX/GHNALWN0gKVYs3DMu3f05hiARsY3pKDD2UVR/UWJtBStqWzxyOdJZaw26QvYsVnYCzRqkma2Vr8FhVvHtTqjyNaSJjIF/DWcefETovkDA6+sBjeuCRYtyYmzwVyLZVfM2/0PaN6PpNN33u9xWeLz8r3rb9pAkyAtggZcUx1O8d3d/K0XqF11WMWfCvOCaMx0hCnARL0p8L0Bwrpzgz1OFKju7tFWXPAlZnlEOnKumR22dSmL1YHNkytQASM+U4ZjwL71n1gCiwVvgqCLRebFEXKc8EUi970qoraXqwfBjkae/5hsUrJdl8ei9MjAfwKff0QyfzqqnymF8w1QJ3LK/WUnNU65DbtGq3/VdeG1OtaF6KQ2eWaoFe0pn+Qsws08U06i/70zyvVu4nkhYz8XKRRJXVaZ8E9Mid/1/dZ30N1Bj0L2WVkQgF4hbgPt4eoIHFTqBpgcNrcsMCBONiwPe6SyEUBAtMIyqw4i6WhET8NVEpbggE7wWyJ4hs5+NKTFivYQRZqaaoij0Ps2RJdmiQoGYtyE9iCXjJ2KhCqgFZjgozDfvE7xmYE6vSv6/7zaBdc4gtK/jiRLNeVgCstqR7y0PoPZBTKJigaAE8/58Z8qvghVSUQjpftStOkxQBUlVi1CYI1DwtTGwnYUp8fJvHwKV6B1QUAInFOnk4xr/ffYw/RZgiuBK3dSgIBjjXi4Ob1Apy5Rb3t9KAMY5cRgHX0GwM3BoUZphGAaA/mULEKE2UF/wraxLSxpjv3buO0+DQf0YAvac0KXys32NpHHzLJyetldQfNSMmVFOKuA0emk0Av5QwMREdjuJsxrg/AUBxvgfi60RNYMwItYQ==","layer_level":1},{"id":"3f59a04d-339e-40c5-8c7f-c98ed6ef6d8b","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"环境变量管理","description":"environment-variables","prompt":"详细说明环境变量在kami_gateway中的作用和管理方式。基于Dockerfile中的ENV指令,列出所有预设的环境变量:serverName(服务器名称)、gatewayAddr(网关地址)、portalAddr(门户地址)、shopAddr(商城地址)、proxy(代理地址)、proxyName、proxyUrl(代理获取URL)、proxyAuthKey和proxyAuthPwd(代理认证信息)等。解释如何通过docker-compose.yaml的环境覆盖机制或容器运行时参数来覆盖这些默认值,实现不同环境(开发、测试、生产)的灵活配置。结合build.sh构建脚本,说明VERSION环境变量如何影响镜像标签。提供实际用例,如使用环境变量动态配置数据库连接信息或切换不同的代理服务。强调环境变量与app.conf配置文件的优先级关系。","parent_id":"53d903ba-6508-45b8-b48b-b3d00d3ed07a","order":2,"progress_status":"completed","dependent_files":"deploy/Dockerfile,deploy/docker-compose.yaml,build.sh","gmt_create":"2025-10-08T20:05:30.6861374+08:00","gmt_modified":"2025-10-08T20:14:26.0875825+08:00","raw_data":"WikiEncrypted:mJFb0eo+82adP8NAeq7d4FgcCqZafL0ho3sap74cjubj7AYi0s/CUFToLVOsgx2FStaMd7X6z1hZ1Y+D0QL0dYsxYCif4mEyT4e1gbSWXJ89J/gHP6akikdtArkgZG7gMlM2b++cB+ycglVtWAHGlPpJ+cDO7e3W5MgOKI2MHzSwbvlflTxuF4BDzfBMu2+IAl1qpXoHcDncWKz01wAdRCv6dyzS4ivnlf6f3Htr6kBXvMzaczRUFoqDFBFQS1XgRQKlKx017CuJEmZi/EA8aIKaViaO9VlIhKvpMYjCNAPhJ1WgGOYgAc/ctAqHZw+VaxasqY4sPkhvHUx3gYbJCnjiIEpQE3+Hvzp8/YVkU36kgADJRa1PQx7TBrlL2DYWWgq2tQCSMrEpbTDWNW+4hY9KN1d3HWGwoU5fj7SmrgpALnIJm1rEeBq1Er4sdCekuAk2oMO3PagQWEnojy+zvmj/mbhnVrAm4jCPxerFfc4BqOX76uUYbYSk0IvrYDjMRASf8dTVnSRjS0Zvwo4+JtQXecrWbuSGSgW9z8lj8GuAX6gm+ht27vPn8z2vZlsWz9MvKX0sEzZx4c6SXxg3Om8j4z7Y2IdPKfZnzJJxRrp1IHzFxnXPgKUPNjlTgIp6T92wP1BoHeSKH+RRpuOzLdo8NCF+gsba3dAVupPSLJyzIpKcgMelpCN62RzvUX4aOhHWwefSSLEzgKXZ12CmJlgappj4sxNm+sVFThxc6NqJqIidxAB8Q9nJ3NiQ+bZHTUqQC0DbfxX0QteYS0tofsKF8BfBtdR/lzsOc6j2ZNq958iBc6eKPhhSjtFNKxgeoSxnpe9sVCRDgfL46m0KqxPwjXygpixpXMaLH97EoS9vMgK1OtmFU5JENUho8UfZrelKRgZwGpci6FCYhyGCjrhUz+7eyo7Up+vLhgvM8sGTuKB9w1PyQQDXfvAs9U7OvWVC3FAmuFnOQFiooyf1W5TuXlaNcbwWFHY/YwTJ9r4u0wWssjtpAPeqc/eJh/nPAQyca/Gw0qygeIFbLW/bBWc+QbDlPA0UA6Cj80u7wCFmLQ7ycNGD7qMDWj/4J4h6Iv28z66LePLtwQbeOwNXljnoOmp9bOUJjefvzUXl8XeGHPvxR/CSclW4S4B1Krg2PL0SYaVrnAkDEYWdpFTH+R8gtBflgR9Rs+bgUi1WkB9nlsYci/XhlJgJgqRI8UadR9MP5d/CGb2WquE/HkSMN5ozZNM0UCzAuwUzTPInrkhWBMUFd3Xv+Hygf9lj4nnJHrG2yX//9IWYaHt1OcqhZzGEQaghBd1CQgwOTNlYxEP5xsBjFE04Lr4qnKnxECnYd0zbFOxA7QFaKX/V51qIt/HrtkW55Ai/jx7UQ7EvvHG6Pnu1SiC+Oat0RtnNAB0N5i/yyMUnHPT9J1/t/LrJf0bVyYzuzKuslBIBSN9maj/facs53NglqRnuR2X0DbPZ","layer_level":1},{"id":"8af4b541-5a66-4fb9-86b1-7c95c9f63ab0","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"任务调度架构","description":"task-scheduling-architecture","prompt":"构建任务调度系统的架构文档,重点解析third_party/pool目录下的订单池与任务队列机制。说明OrderPoolService接口(service.go)如何通过workerPool、eventBus和taskPool实现高并发下的订单处理能力。详细描述NewOrderPoolService初始化过程中的资源配置,包括工作协程池、Redis事件总线和GoPool连接池的配置策略。结合event_handlers.go中的事件处理器注册逻辑,阐明系统如何通过发布-订阅模式响应订单提交、状态变更等事件。分析task.go中任务执行流程与order.go定时任务的协同机制,解释getAllRoadUids等关键方法在路由选择中的作用。文档需包含性能优化建议,如workerCount调优、Redis连接复用和事件广播延迟控制。","parent_id":"1ccdc69d-fc3b-4d08-9be6-169095e4a163","order":2,"progress_status":"completed","dependent_files":"internal/service/supplier/third_party/pool/service.go,internal/service/supplier/third_party/pool/task.go,internal/service/supplier/third_party/pool/event_handlers.go,internal/tasks/order.go","gmt_create":"2025-10-08T20:05:33.9961378+08:00","gmt_modified":"2025-10-08T20:15:38.6055418+08:00","raw_data":"WikiEncrypted:sdobwW3Qsckh0ghPExsMqpbA2kkBzWpnGwF1S6hiyzdcrCpDnfd+fJ2ZR1DgJZfvij6wIbt/8sRpS8/oEhtR020FhxyauEwsjcrlpy21Y08jvQoGS6omHTgHFM/rSqu/Y8LU/OGS+gZJHbONfOj31pyTSjQakrCteFrFHCWoC6bW8PZWekrym3ZS4Kd9nOQOsk0+FjNEWFA0D0pXrX7+1eCs5YeWABjCBHRhL1kszsRbho/aGnGhS+C7VgRBubOy26quqpOVSEpBTBU4/wgdkNgS2HOLpOdt5LBzuov8Ti36wMfZlzdLg15uFtVJ4/MbzDECgu98MAkIU3yq6govDb2lMmkCByo/1Lvtkg1G3IWVOvbihTwXtTX6EiJkiHt8xb7eYCxElDRr6XeutTGnbdSdXAzf34adAWgxUiP/LB/Oyzt10tT36MJB4QWy+oHcKuTnrzlsFeCsmT6YpFI70YElDCu5ukTeEXa5kaWn+yS6TKIbl+keZRqZR6EWXX6VrCL3+RqxKvIt+VeuXrEnP480vh2KP6DLNJBXYAM0WOpJJl+xUVYEIzEy3R3o/2xvLNJSGTRvDbIdcarJWyDqZb3MXfUpZb389nDv9iHB6gWqBROb0Yml5cnRqx595YxExE/IbvreTVy7PH3eSfxKadHw5vm6+2GLZDGVm+LLbbPHH8HmIbQxD9TkGaL9lqazVck3pJeD/N9yFd1HCaRlGKSBJPDSfagiSwZ6zNJIgQfWJm/AjyB2q31340x/+0mKzsSDiDmAGrg7rzpkDAx4eMwktakESZvHild7u9P4nMkCsN348uofQIrfbPM14lmRFbva+6rn5KAEPpdWmzviR5HBZQ7jsK4G9E0fuesJt6HBZ0WrwVhHLIiTkwVNtwNi7cviRUYHOPGTQ3z9V674FE1aQ3U4eXOegvRbjxQz5IZZAHvvL5Ph2kgZD4/T6TJUBVj88Qh+bt3yiJCEyf9KwLhWUEZpqH76FrhBCdoR00dJc0Y6JUYvBwlDzVa34yGL3yx/dS6GhmljqmAZ9Zspk9ZWcuXRVXJo43FSg8agKpwbwkgiI2ppS6p8oogEfNdWFV87W+KdF7azQejSXNuG5IdyAhdjbjtFoPithQtOtLHmFOYiMY1Jlp2B8q+JVx2QbN4hs4qNRvZIzTHu8anG+4F7A0IIaITL6OR9zgXBqhHc9kHOZtJRNOXTK1d3hTPDFsWQE2plCAtskNWD4Fc7186I69IF7FGZZWm2kpq10wsvFUtQulMaDx7Zaw9O67Qljg1TRRIB1U6wkdCg03KXT35W5mIPB9o0WJeikaqQf0H8kbkU/ZymVQQZhkJw3op/uRwuDsSItIF6EIUDcrhwI73+RXrGWEcuhG3/VzR3pDV3QI5MfAi+egm+sJWhrV2QcghzOugO8m8W/Knh1PyNRljiWIOlHQJP1HpuaA8XbOojXyFGm6ed3DJodR0T+VmgUPArDh3O6zTAvCclUSOKY9vljdEAj5NB1RgynhH9H6wDRp398yRRt7AAD2IEtsNShEHmPOAOVjbQfnSqO1DbUhQ+9iBmEVScHy4fZO7OQqzkRBnhXPsvgbfI1YKWP6NNp26IkPR46HS89WUDlQE1h+JT31Opb2v6oLu83pRmcIVLHmPWLA3n6jfjjiF8jZI5LGN5gcywxUXAjxwMgl5TTNrWRU5cOwLgqTbBylWl7urnO1Sg6UzI9VfRhlnjA0O/","layer_level":1},{"id":"40a4568f-d8f6-46e2-a301-107062e68778","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"Span生命周期管理","description":"opentelemetry-tracing-span-management","prompt":"全面解析 kami_gateway 中 Span 的创建、关联与管理机制。详细说明 Span() 辅助函数如何封装 otel.Tracer().Start(),并自动注入 tracer.name 和 span.kind 等通用属性,简化开发者使用。深入探讨 CreateLinkContext() 和 CreateAsyncContext() 的设计意图:它们如何创建与父 Span 关联但生命周期独立的新上下文,避免父请求取消导致后台异步任务中断。解释 CreateTraceableContext() 如何在保持追踪链路的同时传递完整的 trace 和 span 信息。阐述 SetSpanError() 和 SetSpanSuccess() 如何标准化错误和成功状态的标记,以及 AddSpanAttributes() 如何便捷地为 Span 添加自定义属性。结合业务代码中的实际调用,展示这些函数在订单处理、渠道调用等场景中的应用模式。","parent_id":"fd2a2cba-0887-44b8-93c2-9cc9e520daae","order":2,"progress_status":"completed","dependent_files":"internal/otelTrace/span.go","gmt_create":"2025-10-08T20:05:46.2714253+08:00","gmt_modified":"2025-10-08T20:17:08.4080837+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoBD92U64q//WUZekSRqHD5dHvMGCTFBVAVmAVyDQD5vhdwOgo0VUMU8J61yU6Nmdlhjw45DnRWLgYcJJ0fcNbzBX0d8MVmktcot6LmM0W67w62771R3jGtJ7Pk50+pmBCIGvVPnk5FTOZMk9+pmyKUkMa0aNveHpnFJClY7+3aE2GIA10mgDmYc7XoXD+vJGYoizJS4xN5g63oAReXr4T51jUJkqn1bSheDlL6tFa1j8kWB/39b9gp9JnpDFsrb0Kzq8UjbdhCeCS1cf5Rln3Xr0WMZ40LqaUECj1bB2W0i9ot6xVnls8EiZRkbsVnk622PYv4Q9FXB0svDBv1qIjKWx0BnwrtaT1ldfbJMM6lRANdOTsxpEs9BhO/OquI/MPyR2pHjAexE3IKGnM0KzxbGiQFjmvc9lipK01/nZpUFtXT6ZXJKF9tYSbalC1zlOZik0ZyeOpZRPVnkC5cfi5FjMB7CWZ/W95nbwFrhMIfKw254n/QuqMRu5MvaDBo5WK40+egL0EVmtXcvCdds3DbrItGEyiCraFLfcPQZbNnU43aYhUYFjUTTI3OhqVSoknsPBRMpAgd42JVHNQuVIxkNDS/nhKVi5IYTVhZQPH+9Op85Q7CkMizwb79v7JRV2ejqqccPI4iAotfsgN51tQ5wBhU4lE/Aca/GE1CJvZRQjmHOQfm1US8FDuPvPGg2qCl8HW1xM/UtxaTm39FZUjTWHoTFoqhTA3CbbFa5oZNi4cMcQM7ALoBq7a73JsqN8Yc7l20vrlZKPKC5dm30foWyJJpByQXOWDiyEbshHZabW9EvvMNHnG4eZr7MZ+z1pj86wSA/k+Jjx1rBIQCYmMUnvx+jn6aa9AKPmd0CG/ZUw4ucCDZ9l8rB5xrLWPAkxh59O18rWJa8lmkylDgps3G4Ui/JeGHNc/OOs5a1CUhrJsh2ZhvjXY9cu5gl+kbLfX5e1Gr0mZ30DSJv2ZnyI//aOMyCxJvl+0EP9yJK8tlrguiR9jzHld2eRahxya+rthkFlPdVPcG7A+fMBO1b5Xm+Ntzpbk9vC6tH4/S5wpHBEcStLfpJmeK49yZx/izEKR2IzGyxrO8M0pHHWKjiSgJ5o3FjDSzL8BFeDNd9k8Em51aoGTAi1zL0l+12m6u+u6vDXx26YhZ5v7dgyFOadwqHy7RR7A50O04h6nKZ6XuEDOTUOiMzu/MVGA29mAvBl6QveU+CAo896s+kfwI+0nV5R2/AQ+SkrylFfy5pYuIyZN4lS+8vHJQWqfc/YtaPuBBJGctvJPEGRqiBFAT1JNBIDTb2avxhd5VZFXLmcMTBJcXkSabvUmLHoQe5goDO5eQW4Icx3MpXmzplMCDDIernOixGYTEaGFL+7Sm9Ndlr8/yWHLpLQU5mNTPFUU6+xziQ2Zs8yJKGZFm76xo+p4FpMUCAFWGLbX7WcKpZ/SJacGkGEaENn3BgYTaEudLLDgxRon/9M/3eala0k4mo2vzX5TJKq6PBcvl7X3Bh1Wn5VQ==","layer_level":2},{"id":"1fedbb41-1015-4ec4-aaa3-c732e30b12f6","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"采样策略与批量处理","description":"opentelemetry-tracing-sampling","prompt":"详细说明 kami_gateway 中 OpenTelemetry 的采样策略与批量处理机制。解析 traceIDRatioBased 采样器如何基于比率(DefaultSamplingRatio)控制生成的追踪数据量,平衡监控精度与系统性能开销。深入探讨 sdktrace.NewBatchSpanProcessor 的配置参数:BatchTimeout(5秒)如何控制批量发送频率,MaxExportBatchSize(512条)和 MaxQueueSize(2048条)如何优化内存使用与吞吐量,以及 ExportTimeout(5秒)如何防止导出阻塞。结合生产环境需求,分析这些参数对高并发支付场景下的性能影响,并提供调优建议。","parent_id":"0ebb9117-99a5-4092-862c-49ee70ccfee0","order":2,"progress_status":"completed","dependent_files":"internal/otelTrace/init.go","gmt_create":"2025-10-08T20:06:11.5781251+08:00","gmt_modified":"2025-10-08T20:18:01.3430547+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoDsIAIxUszffcg1n4BKyPc0aCrh3XHDd3xQPINQN1cnKs2UlshAVLYNB682wpS9K+rHiDRtzevtJr0BIvXNsCzvE3m1W2V43gL3oyS9J3BkU2aQ3MJJKQrM6fOHFLiZQRbYn+xzJ9SYt+tuST4mw4rVleLisFHpZcZqsynjdKt0O6Gr9ESyApUIqn8iJZyS4gosMMUWYc09/QrsPa1tJ5qyOLJKkjNwAPU0ahg1NJRGfRwx2+RWGkir38p3DN2ZwC7ZRexa5+I73sK8+v1dgxhig1OUAuEF1GG+EI2w8YWE/sqXZiiuUTZ6bCNomJqsq8rlW4hffLJ2aVusYV5barBxiR4X9vAbdYRwWLAiAAGfi0Sh4Rbg/W/usKTxvBXDmApYmvcTcwyEL/KQUbrAig/tW2A7CJ2Uy8DQGpZfNpQMB1c8WgCwj1wIdhpeH0EmoV3Xtu/l22oixvdyXvnwei3LTH+wmEBuXjnZ8ehvitF+7GxIO0j5+wwZLZcoluOkK+iB8GTCWCqxNl0/BQM2OMqa/dQT4e6xpp222d/qGIsryqpN/7niIHQVZCFjOqaX3nU0dBXPfyBqQWAGBEj7HHwHbXYAFrV9PFT0GmlVyhAM+tL+jzCJCoXdJgvB+vvTmdD8zdAPzCOcct/IG68qtQHBv4WHhL5beEmYp5OJP18aMFey1Ei7fCDq/LwJksRIFrDzwNPrIpdQDbePyC+O2g/mPcg61p2WnFpAg1hR2t7dNj5CJsDpwL37t26wPgmDOpVci2WrE1iMSLdNekLrktgl+U3ce0SLl+cxq4Zkvyn+8MDaXErU0yORZygxHhWa0oKu2HJlMRVlEA+1QZMW4RxbKPVndCeTYnVppfDfb5TL1ex1CrqpM0JS5v4Fg139fomcnlqK/XlGIACiszGcbUQ6OmQUffmqaaujG25u7OiehvEtHQWkxIiVbhtl1tSKxBKzh+91mZuVzJJcLaqd6z1JNRzohAXBfJMJTZkYCe4heWXu4Pbe/RMiTMiDy8e95rbJM+DI6oPH4i0bW2+GPQkr/q5JqaOi0ey4EtPAL3oqugpC0Rq7DiNTZep8wTDjorYWJxwss1ZiRumt7Vub1rBlZdAJM/KUukLu8+zFw+5OYT9HmNfXDV6YnO1ucbl8SkE7Qs+FDFETAefqRJZXJf5lj2VR39iwL2J7fPiJsAaHFQ==","layer_level":3},{"id":"a5d56738-c20f-4178-9f81-d01bb592f194","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"数据模型","description":"data-model","prompt":"创建全面的数据模型文档,聚焦于核心实体:订单、商户和账户。详细描述order_info.go中的订单信息模型,包括字段定义、数据类型、主键、索引和与其他模型(如order_profit_info, order_settle_info)的关系。解释merchant_info.go中商户信息的结构及其与merchant_load_info的关联。分析account.go中账户模型的设计,以及它如何与agent_profit.go中的代理商利润信息联动。为每个核心模型提供ER图描述,阐明实体间的一对一、一对多关系。文档应说明数据生命周期,例如订单状态的流转(从创建到完成或失败),以及相关的业务规则。同时,涵盖数据库访问模式,如通过Beego ORM进行CRUD操作的示例,并讨论查询性能优化策略。","order":3,"progress_status":"completed","dependent_files":"internal/models/order/order_info.go,internal/models/merchant/merchant_info.go,internal/models/accounts/account.go","gmt_create":"2025-10-08T20:04:49.3979036+08:00","gmt_modified":"2025-10-08T20:08:34.0332817+08:00","raw_data":"WikiEncrypted:klcgW2PbPxJambbKMzvFtzKMOkAiMygw2jhMWheBgWjabVsg22USnmOBp3LIxuc8I5oEhmwc+cjSueyWYZre1tSOmU2DILRaLVS5z1GxT7b1+PljaBuORTcFJrCXeM0YQUrxF320YEotDDoSIIXzU87xA2wBqxAusH7/M4pu5NE0Kjh5aqW4fRuzwkdVKeMJ1hsZSGjUfZLP+HC1eTq2r+PbUUWpkE1T/tGgfx+BKCkMhfLbDe5VGWmQDOzOs42wFmiLBRs5/SiaMKe0HWzyWznuJuzJGGv3S/BOSY/FP4h5GPntRivq/nE3O0FKvUd/BUZpW6GmovZNQXLPGN6XWI3KTYrWP8LHa/iqQH06DhcO2jkSTR/6bhmyzWyJs5zJaPQSwq59KLCs6wok14vMYLeP8/4BDk6vtxU0YthjgSwxxdUfOW8/uOQjdBKp19JYPVzGmKlx0JsOQXDQsAsTmAI1RygpQRsC2uAEPNn/u/omTh64g+YfyxtwlfAz/txZb6vAMzEMlE0J7fToHPwp8LPtI5ghix/5g/Z3mIU8Xj80crQP1+lOv2AynXCZ/ikGjNJzvYk/2YTN0i4ISrpdgmOTNaZF9SGYHy5G5pGs4dqnGBELaAcACrJMb16OSWEID8KLOFuhjyTVobCgVVCC9OA5v7Okdz+k66sK5lqa2vAp80EzJ/2Bt5H+8HpTc7IuKyBIqU9huAZZsX778VnoN7F6LJvjaC9rvEXHnBRP6mUsJKa8PO6TzQUu8iAyxcJ6+vQ9pHp+3X6/ANsomu/S2qBd5tlfEU9UguJoh3ZkjQj8+DYgSkyZ1zzV60vt4Iz4xZOMbQ+pupoCFkkQUjztpgqoPjgoTHgJfRfO4Sg9jkBwT1+ajbPZmTVE8JbK3GVyIol5iu9GHNSfqn0A+lZHPeuJ2dfW9y8CkeU3HU1GVjjvNrco4x+GZ0x1lZVcq3cSwvU0POo4N9DjIS9xnXL/3/4DKCtg8Fjlj4LHu7IJ6rtn/z/SSNtPkOBtmI6Ha44dRkK4q+ayPJpu5z9UubmM70Wj3BSYkM8GoZGIElSSoHbZhdN1S+67lZBBIruSBJliVujnXsp2oyMsTqLT08S3mKR/D29MmMLUEiShH58gLE1utVZeXIEELNMuZSmW8I1FEXbnGMc/P5TcaRXVV2b3eRJVb8ZIJCHjy+zl4YmYloCPk/k1xuVeazqFcl/BsvqVoWpFYPKyRZTlhVBKcs7g/qiUhfbVtwYItmuEF4b/KArPf4pvk3bUMMCkZQAc5HKQqpHQ/d28lbOqw/gVY6PoFBjYYiWvhVsnieEL6vfx8+gyZsjkI6Te0GFotK1rmCK7Auw15cKUFZpIu7uH7F7EgfVJ7D0T0ulM26/Q926NFle49aOtTlzvVuyGJ3W3EbLY3qjGls//F4Lg2cRIjfS8FRJa27ptWIhhCV9RtryoSJ4pNY/NzE8ZgupxaH/cq6FprwU8rKV90QobEWis3fnKscQj5V+UsJlybWtyOtTBsOjb3566lKUugD7eFBsYYYJW0cSgPZW6Cleopd5Bv7D3+dDuqjd6DyMSfiR1wYCRXdM="},{"id":"c0f73068-9c54-4cc7-ae03-811f69af12c9","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"消息队列与异步处理","description":"message-queue","prompt":"详细描述 RabbitMQ 在 kami_gateway 中的异步任务处理机制。说明通过 github.com/go-stomp/stomp/v3 客户端实现的消息消费者(如 CreateOrderNotifyConsumer 和 CreateSupplierOrderQueryCuConsumer)的启动流程与消息监听模式。解析订单通知(notify_info.go)、渠道查询结果等事件如何通过消息队列解耦核心支付流程。介绍队列管理器(queue/manager.go)、任务处理器(handlers.go)和工作协程(worker.go)的协作机制。涵盖连接管理、消息确认、重试策略、死信队列配置及消费性能调优等关键主题。","parent_id":"576b2803-bcc0-4769-89b3-54c89e6b7381","order":3,"progress_status":"completed","dependent_files":"main.go,internal/service/notify/order_notify.go,internal/service/supplier/third_party/queue/queue.go,go.mod","gmt_create":"2025-10-08T20:05:11.086892+08:00","gmt_modified":"2025-10-08T20:15:18.9609185+08:00","raw_data":"WikiEncrypted:IaaHBhg4aKVK2Z27STIpf/b/nFD+cBUnNsF5DeWv7A1urYlY0Tcn/dsclaHDhOF+ypTw/p74KK09fCSdGKQVA07NZvyJSNTYCKMHrKMBxC8GnxZ3dSOG/TQ9IBFxIPZ8165juzSJk+IBVODxNOzPoRI2mOkEzK0skIEWx/vMOLGHvYUb7mSXrxhiW4V4NaeglYPEp61lKJa3Uq/yjtivEL4Geaohr68c+TR5HvSkXeMaVauxboAAegTCM00TPbIKJ2lobxB7UaIenxkapur7o6Y3slxnysSEZeqlFbECpC3bx5qX7eiB6qZHnLaXZmAMZGbA8SLBpy04eGEKRgCPDvtrKOuSYEhpVtEPR/rfJIdCA9WV6F5plCvaly8+lVSw9N+NhpbDrGomRAEDRbV58txXhiy1jGa1c7SBvsyAtTOgp/fTk/m+pAbef1W3ayqtKTe6efDZ1Yw3DDe5LAUWbTnxXSLsWJgAnNozCBzMd2yMuPnhdVF93oTQ4Aw0W8Aw5PXskIctyfBcR0IQHiccS8kzXLMnNAt/oGnJFytXmye7qc2MWe1GW+zH8bCrOazhITJaMINfpgBINeJ/Z8tmnPn0o8rOFhT+vgnWVXNP89RTC5rjuqGhn3Ud76ACgmCZWhgW6QSiVZGf9J4KMXCFw/G3LKWyjG1mef/SSsI332L+rAzupSEA5EGPpb5EoqrmJbkUfNS7+tDgroa5j4+QigCeKrkE5O1VhDr0izKrc3umDp26e42UKSffOK8Pt2iOuf1fMhJHDexi10S0KMMqzhAav1m3b4pOWCWaWwEUCu4v4sEqRinCL+kK2o7IEwCe1zp5VRD31cYZ3aTlqN9WMMSUPaLksYNDMtSG3AicBZH2qBWEXypVzoRgOkxrbq/m7nNIoFj8ScGN7xt8M2JOL2yxKAzSFa6/ZMi7HHDzgvI3PErLYS9qXjmc7O4HKnJ/i4JqtL8p3qNzGMokXdPpbk/upLxntRvZ39JxZgmHo0SXYVEr4YsEfP3HO+vzGYujMj6FTJDT8DpA40KRmtSuo2dkiAKxevJDl/P46mmx2lNKRn7uZUiTvJbn0RoOzuLQ7lPVD8BjW2wK7B1upzv6iNXLWM/w5PleEel7IaoY8Wi/uOKPzhNxim+RmRfh3hSU12VZc8vKXWnwFlC1vqWFcTOnDGkE6gznOtxWEDVq9nsxXUezQdtpfxCPwlzbXyib5Y1wquy4ZoQ1m/ICUZzdYKGzRo8YrSHnZn4Frp313OfoI6DXVAjrf2BY5kBdRSDxnHQDpi+s/T80+clR+h+7z/L+aCi34C+UO1wS2y3HYA4=","layer_level":1},{"id":"15483189-42f7-4bbe-89bd-55f035c33ccf","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"回调API","description":"callback-api","prompt":"创建kami_gateway回调API的全面文档,覆盖所有第三方支付渠道的notify端点,如/mfcard/notifyV2、/appleCard/notify、/tMallGame/notify等。解释这些回调接口如何接收来自不同支付渠道(爱博、京东卡、天猫游戏等)的支付结果通知,并通过对应的Impl结构体(如MFCardV2Impl、AppleCardImpl、TMAllGameImpl)处理。详细说明回调数据的处理流程:从接收通知、验证数据完整性到更新订单状态(通过SolvePaySuccess或SolvePayFail)。描述不同渠道回调接口的统一处理模式和可能的差异。提供典型的回调请求示例,说明如何解析回调数据并将其映射到系统内部订单。同时记录错误处理和重试机制,确保支付结果的最终一致性。","parent_id":"80fb1e42-5bd2-4870-8b88-77d31ff5c478","order":3,"progress_status":"completed","dependent_files":"internal/routers/router.go,internal/service/supplier/third_party/aibo.go,internal/service/supplier/third_party/jd.go,internal/service/supplier/third_party/t_mall_game.go","gmt_create":"2025-10-08T20:05:17.6849003+08:00","gmt_modified":"2025-10-08T20:15:38.8092672+08:00","raw_data":"WikiEncrypted:ICiVViANlur9hTgF3KdhPBHe7iyNKaUrLIg0l7sLo7hTKd8xk03MceVQ2xU4zmVOKSnSmvPv/qHWmU8lu5XU9Ag1D29u+6w37saFWSFEINiNkFNfqI1ZUmqFOt8LT2OIehnvWEPfUqtdV36ObR6f1OqA1SnMck4nQyQRL0H4HnYgzDNofwi6rWFmwjgP725JI1YYarnngI7LWf3yYPYmDXtGvGUq85ArOascFxh76yz20xy+/WkHDpRquNk9kn5Y0u7H2qhCstQDHgGqMLoHy8fShb14Ikk6V+s3+6y2YIZpxn7ctIMk3OedQ9V3d4JUQLZzIpNgumEx+npS6lGMjjolfSPcNL4SCt8SJBIiiHHD/zuOyjlXEzxJ3NFMLwaLrLRB4AJBnXz0MOlS8b05sYQZ5EFRPnP2xHmUSrSpgC6PCXbL5bv1Q0tDcRc8bX94fKr7j5gvj5hHXUBu8L2V1rmRcegHfxXC/Lu8HMmGFsPpobtZmIozQ/jOoXle+8yDLSlDYEocIZ+zOm9kRwpjeRxVaZmcCujr/4Tcm+qZNq42HADeSFxWE2kRfT32LygmgwRIVhUg/zU/EJSgEA6U64hdRIWJ9j9NMfUUkIkRBCM3yz6WdV699gO63DiSKnaJC8kLe4UAsvrXsnIgPchK53NXgID0i6OtHhErrkBATefef8z1wU3hE6TrEwvYDXcCmHeb3p5t7EHHK8UARvsDNpdIz5F+L3Tgh5yLb0PhEQBWAXVSUod/httvdO2tUkoHxY8qr3kLEmTzh1ogL0+MOX6lY0L8yTIYXtZqVHUqKjT4S4Z4/ap9D3W1fsbarkKD6fviUmr8EyLO/b5Zu1csDmx7z1UU2oh2e/FqZRq9mD5yF/4d93d0bCCTMLo56AodO3DMFgU1aaAN0ytN2WGtNGhbaw3WD780dB7DkzG8PJcVlA4eLj7q26wBpYN1Z2XD5eKGeb/yLjEe9dYeJwdvUZHagQeFn9Lwm2Apnq085MKk1nE9jtZmjVumQLJYjBjqcuj6tmYdMQysh7hdNBevFcSLfuGbTB9eNhqANdyQwBpTdXRHQMEZtjBttuxc+2G3uvlSdWeDiYZ9wWdy/QUHleMow9kqTpqi0ThLFw63xet87yoFIYdQSRGETRT0JtfZDjR9qHwrdksCY9BAoWuwSObK1y05fDL+WmqIXZUS4I2ZN51/hohNxxOURxZPcB9JRoAqxWJbM+fLWipiKZN+UlzfahzmVHngEpNeC93mrqHBG1d+xrtz2CRlMTuHA0Bq/S6crtAKsND+H5qU4dq90q3eIW/TBnIpLmeMNdxZy6iAjX34yrTKHKYWWMDraH9O7PWqQwTYDSSVkpr828tfKXov9t7ZVnMFyaB9CnfTLIff0AfkuY0DkIQy1HdQJDy1jQCBVZUw82sbm43KJaR6zEwRebr/hGynHAy9kq32f8hxJzG3bpoYwgjQ/UFMyhN1mwMaFaBxQxkatMnWDeXCIEE8VQ1x/dak4Wcsz95enKk0za+xPwo8pja+D3+PN/pAPqvAH+pnmgThsC5fbKUZj2NHB2YUcydT6cIipV9sstE/gzDlT3ExTQIRxzn7LvgF","layer_level":1},{"id":"556f07d5-845b-4291-9b39-b0872940a3a8","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"日志与追踪上下文关联","description":"opentelemetry-tracing-logging-integration","prompt":"阐述 kami_gateway 如何实现日志与分布式追踪的深度集成。详细解释 CustomLogger 结构体的设计,特别是 WithContext() 方法如何从传入的 context.Context 中提取有效的 Span,并将上下文信息(ctx)作为字段注入到 zap 日志中。说明当 context 为空或 Span 无效时的降级处理逻辑,确保日志系统稳定运行。描述在 init.go 中如何通过 otelzap.NewCore 将日志导出到 OTLP,同时保留控制台输出用于本地调试。分析这种集成方式如何实现日志与 Trace ID 的关联,便于在分布式系统中进行问题排查。提供在业务代码中正确使用 otelTrace.Logger.WithContext(ctx) 的最佳实践示例。","parent_id":"fd2a2cba-0887-44b8-93c2-9cc9e520daae","order":3,"progress_status":"completed","dependent_files":"internal/otelTrace/logs.go,internal/otelTrace/init.go","gmt_create":"2025-10-08T20:05:46.2778114+08:00","gmt_modified":"2025-10-08T20:17:17.8120722+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoDv2B1PcPRFDVcz8A+RwiOsJW/7A5d+8LUae24axAjLEBQ3+V/sXNwuTc7IvXUHHqgzMr9Nq267ZnkYahh0fj7NG7aPLtzS3Czx9g3QF+RMpSTDNk8zrIpaVYv18/yV675MJ2e1bGQCul4v5E9yrhfFssJSwDNy0y0uvj+7KkOjZcal2LdA5sboMa4yWvcIGA0ytjkFw0iq62rnOT8oq4PnXQ589aXJVV+FuQyy3yz2YKVaRgFiPEN2g5dg3HOcGmE/BAW0AQ62aHhEoJBDwEzAjDCoKGQ9jtNaCvHNgrs0tnSqsnFPoyZNzd52qW3LUOG9nGVJkeNgh7xD12znvIJh7ftRW61ARygxqTYg3ti1baiViFQi+3KQfdM5lvYstgJPYvh4iZybu/2JcEvleSMzHqjyhxOY5+GlWUPsIz+aWFrQXDAI9+GeP3mFlhQynSZ1ETLv88zawMZudWgmLehMfuXlPbndtFhjT0ZIlS1h4nRov/VqUhMEZc6Kecwc04s/GRy0HtvSMcC+CzJIrgR1LitCiSZ6XKhoNz4ZcPOySFs6iWygM778Adhba4Pdf1bib1r4whiJIGc4E7lFWdyrlM0X7OauC1ZDIpq6jn9aux02AhH1dWiFeLI10owVB8oAjkMANHfgNzXE9DFIho/+gJOOoIyWEgrWbyrdeeQm8+9hNa3BKM1jRQoM9uGX6Fbcnjw9F2nDezhAVTPLEGbkVc+I7QRBfaVWuclXqVDJJy6aeF8UhCv0w3mfZEYiWdn4jtVw7LOEajzvQgev3dnzwKZghGuwclbr0mk5i7Un7UNFaFnAsBTrebYJv7cwDceWMvq+daB2w0BzNXhjtvue87qz5EVW3m7/V3f4H4RIyQ0kb89l+ewVR1hBzhNVRzrj/+sZvgswrjaOxX6Whj3tLZutu/wSnRPVMY9xfu3R1wRh9/ASMKc9EhN0gNljKwLiAOPrdnXOwwEl/SJoCHG148KFrDtaFMeN1P38SOqMNmwCGYl9IKgsgXkXd43la80HvCA4geB/KsXxin6cj1tde3wLYeG+pqn6B9rjaiPDMkvxrFSc5zi9jrNRcuElWQx+CAlUTvVKW2vOsPQgkg1dDomHuXgP8b3GrRwg9uiuItmrohjWLzOx8UslVn1i0xqXy8C1LKTLhSRwxNgO4MH6i6UKOADe20LsCTbG4kIpngjLWXCCgQI7FLkqqT9VjoXWvFPVOKAQxcyxKlx7KvtK3CbdH8AyUmITJPbyDvk4kuX0fn5f3tktYi7Ooj9xw1L/1p+TURXoAmMXsNSPnmxcfLaHhC7AvmaDhS1YwEbfuvJOYqwwhpr1TlRA+z75wREEA22RHsAUzGd9ld8WsWwb6y7R+CeWVNK3Srq7rkPMyTpDA00UpQHJBvv8FPmhdkg=","layer_level":2},{"id":"25edcf0d-932e-4a7e-ac78-00f9888b6ac7","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"分布式上下文传播","description":"opentelemetry-tracing-propagation","prompt":"系统阐述 kami_gateway 中分布式追踪上下文的传播机制。重点解析 otel.SetTextMapPropagator 如何配置 propagation.NewCompositeTextMapPropagator,集成 W3C Trace Context(propagation.TraceContext{})和 Baggage(propagation.Baggage{})两种标准。说明 Trace Context 如何在 HTTP 请求头中传递 traceparent 和 tracestate 以维持调用链连续性,而 Baggage 如何携带业务上下文数据跨服务传递。结合支付网关多通道调用的实际场景,举例说明上下文传播在订单调度、代付处理等跨组件调用中的关键作用,确保全链路追踪的完整性。","parent_id":"0ebb9117-99a5-4092-862c-49ee70ccfee0","order":3,"progress_status":"completed","dependent_files":"internal/otelTrace/init.go","gmt_create":"2025-10-08T20:06:11.5849914+08:00","gmt_modified":"2025-10-08T20:18:48.5953037+08:00","raw_data":"WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoAYuIRNEi8iwu4QgZIIA/MkCXvu5RTXNTW8eELtw3O6g/VgWhwiurL+xFX/9XFMKWDQtfh304VWlHBQcnezPDJmRFygD/K5AVa6CA35UWSkpsMWmpZ/MmvQUqQC0VHsqMkGf7yv9XVMyAHjKzWoXtk1D4rAu0Ie1VbWfLmaMUmVA+e7GqxfWGy6RbmxGX7L9dDxcD9TbpmHYVPOUGtMht1zmsnHZ0N/I2a7kXmwSLzKnFMhK64uSg3Em62MXxfZGpH494ysLsb5MnX+FzBxCO7sakeMZ5acOEX5NdszzPleBbAAPUA+tJx1ftuG8URgzUKNz2yW2ycno+/y1PK2uDuuNvAOmIjxDJj3ypBhFQKNsexm+3pQznc8NgILfVOkGt4QrhH5NAduKR+Nd68WYwaV/MxHqGuCX5uV47g/NtW9epeAXL8dn/EOP7iar0AfVUm4QGy9g4ujXqf4ib7blzh4ANqDRjfFblFEhxvOi1MqRWqyz9HEUjdK6N8/VwkMNuU9IZtl01saJKIUDWzRREfm7c8wln5kyTLR+W0mtSWVep8TXxAxRqKD/R8pq8F+u2T+c4gM34PRFx8IGWvDlXUf0D3sXuUCWMz4gbJ2ckhK1v9MFVIuVKXZyB1g8Uk9YPjQqJkyhHoDp8nILQSP9kBWl02qMsN39EYDQAcujtGIe9YnEVK5b0gXsOTp8/x0kLnLrB6tMzp19l+FEKmVntQ5JwtTeMRpQmnR2gMRpZmroyPq0Q4kbnMz1pQCCg0WsvFukZrg4x3EBFJxwN+PcI8/Ic8WuMoNUd0Oj8DZdX3aBIp0oYX1LDZr20DkvSyO95JbJ+QJMaHYKzuPms1VbSZ0HCEnXEdtBY9cs0R7Mz1dcUqNwN6XTraftau/31McVaSLO/0NtU1+HAfPxPDVADdsO7K/OofkwMmLgG2R3gd9yEHC7i/tRRQZ+lxQg85jindlzIfNkYiY3VqjJEk78roiPg5YVZvXX7l67mruozacjx6mf5g5Z4NMnIDZG4VT5R1UJLlUqazg0i1eaVboLNkfrCAXBBSSxfa8ldUEhTzQyJRO6pvQU0mUpGo7yXUuwwbmHiC31WrqjjUr5XneEshDUI9/Ey+M1R7nzFljePzHnTiKFFz0V1NInkD4IGbvdfl8MwaZt404rpcBkqeX07Kh","layer_level":3},{"id":"1ccdc69d-fc3b-4d08-9be6-169095e4a163","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"核心架构","description":"core-architecture","prompt":"创建核心业务逻辑层的架构文档。深入分析支付服务(pay_service.go)和支付解决方案(pay_solve.go)的实现,解释它们如何协同工作来处理支付请求。详细描述供应商接口(supplier_interface.go)的设计模式,这是一个关键的扩展点,允许系统集成多种第三方支付渠道(如Apple、京东卡、沃尔玛)。说明系统如何通过实现此接口来添加新的支付供应商。文档应涵盖订单池(order pool)和任务队列(queue)的处理机制,解释third_party包中的具体供应商实现(如aibo.go, jd.go)是如何被调用的。提供一个序列图来展示从接收到支付请求到调用特定供应商API的完整流程。讨论架构中的关键决策,如为何采用接口驱动的设计,以及这种设计带来的可维护性和可扩展性优势。","order":4,"progress_status":"completed","dependent_files":"internal/service/pay_service.go,internal/service/pay_solve.go,internal/service/supplier/supplier_interface.go","gmt_create":"2025-10-08T20:04:49.4046792+08:00","gmt_modified":"2025-10-08T20:08:12.4576473+08:00","raw_data":"WikiEncrypted:4PoKJZEjoeT4XL3d+2H6W/6FWVAUV2gnu3I7xl7Vy/iEOxLqpYxB7lCXCUAq+rosTPdhYzRKNIQy4WAdufTOJPO98t1dfZrbfMRR56Banyj9JeWRRO5E29w0EUaC/jEhvGTB+WX7G50HIUdvuld7JhV6eehwvvln1bgBJR3eVUmNHtTD/p8JCfzVsGTtvmA3Gt7Fs2rMU9TKcpUaQBr4xSXIu0o3e4taNjBTU2Rx8YjIeDGIqgiDtTdtcoy9NikVSpCrsptusj+NStyh6DvDzhCiwEKf2HVOKJiPV36ItyjSlLs0cZkZ3Yr0AiMTzIVjqH2G2VfUgPsBmug/vDSnmaX3Ha1SoWlmZY2LESG15Qw6I41sEg7Ke/XODasjyjGl3357gXYhAssu1VBRVVx4kYJ0xXD/bGoshTJcZYqMGgYHM2f0qOdqC6ybrPYmocf1n92fncYBfejKTJ/efbeZQ/D+gRXrji3ixjKa5mvgggFKGVTzzBbKRy7y9iqfzQJaP2IpetXn7Lf8DxBiJ1xdrCowvSHWkGBvRSBx9ytZu4BhJareqjJiufFAV89uyp4Y5kXujTukn/MGjO1Gcu5/aQPxAjPuVdCtfxQeeiReFyOZtoc6EXbms2YFu7mRJ6DThgaoAKAFN0+rqHDYdKr2Agkej5OGEyWQrl+55Euca0VjxG1k7tQe1q1z/2ekLNEFdFR3JaaUK9eM9zAjljgG2d3RsLaLKFudauf+6IKat654mCixtWkG51ka7jH5moM8iqNxlwCBxhc+sq4lhlEDGKRoDMwizJvN5FFvUr9Vzt9sPoe7ch5o7ViWRbKkdqrLj9cUlXPsh8B970WxBMsU/b3kMts30i5eaPyrHLfx5J/3YIEn0kpD4IuOSmrj7/knypkgM2kUNmXPUPRlss/dXhInNvjIAeKiMsZUs5Xl3TcMx1Sn5se09NeWjIrM9p4LjAN9dcgbMOFryYpJQ+7d2PywRIptOiTSh3rjcODFju8RJTsK3aLgAQ//kRhBhm+L5S6PMemQNRfKqLT+IqDQhkMUwcHTnh0gRz1JZuasQAYQ8oPySY2FdzrovLheviloCHpgykViCt3QKGfcyu1Hma4d7bCURLsho20mX/iDvLUWRss8UgZ+LqR1/HJI2tyLtRgwshZM44slvw4e7WafEJ+eWtyIbagWFLC2MOo26594XhUwK3L5ZocjtFo9/V0pB96qiyvd4eKD/aCkTukicP7fnozWPyS5h3h3QftLJMXH/K0C0KhYyzuG0+T/aj64KVMQp637NAq3EGOFZhXzZvmd5X/34CY94v/KZRrlVE9VxlxTRueNTQQ0bigzRaQoDwLF6vN1jCW/aKyjimDRTgzQf9e8ZROJPKDwEg5S8XVMKV5pZ/YUuZ0wFWD5XHg7dwXz738R0yS5q0B4AQOWY8j32cErW7HiRt6J72vqvoOsOu6bmvSYQ407s/XBcG+kdMEM6NkJ8ZQalfsME/tFuw0ZC5vFp8+jtBmZHcDFl35i6ZMaiz6uIA34N42KulQipgHuqztPAp/rYXyEK0RHWQ72/p+tlHDUY6LiA0zRt+k1E5xDbblqDnP6pmnfCR0BHVaMdhR7SRwa+kvIjG+uG9zY+0SFPmtrHpGRM915vVjTCgjNfEWiFh5EGWtJswsY8uX8bdCUeCs/8lA9xzouxjfQxA86fNYuaCJMFE31KK8="},{"id":"53d903ba-6508-45b8-b48b-b3d00d3ed07a","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"部署与配置","description":"deployment-configuration","prompt":"创建详细的部署和配置指南。基于Dockerfile和docker-compose.yaml文件,说明如何构建和运行Docker容器,包括必要的环境变量(如serverName, gatewayAddr, 数据库连接信息)。解释app.conf配置文件的结构和各个配置项的含义,特别是与代理池、消息队列和数据库连接相关的设置。提供本地开发环境和生产环境的配置示例。文档应包含使用docker-compose进行本地部署的完整步骤,以及如何通过环境变量覆盖配置文件中的默认值。同时,说明build.sh构建脚本的作用和使用方法。最后,提供部署后的验证步骤,确保服务正常运行。","order":5,"progress_status":"completed","dependent_files":"deploy/Dockerfile,deploy/docker-compose.yaml,conf/app.conf","gmt_create":"2025-10-08T20:04:49.4126903+08:00","gmt_modified":"2025-10-08T20:08:54.4904132+08:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w/wJu3YIP6+M0pmbICT8qHHN+JclDh3MoqOR1ZyeD+ej10Oi8PRJBW97X4s3q3IqFaiuys2xbl6eVDdT0B1MfTCDuBVTV9ACjY7VtBb7FBC0IcVcUQBob3odCrU3Ve/Zwzmr5voZ0hTxTg5HaVvm/5qmK/J4Inwe3NUANiWKByDQOErXG4DDzlVkLQyrl32yRO53NyOrOAdGlZNHHqQOeh1A1iTbWm94DdB6Qy7siKC6m2EuUqhK1mHrY0p3axbqeHYGq9F8ScuG0f0c91Th3p5LHzimNaEPBh6rx4O6PJGSlwMDz4L4bkfXiNa0sitpvB/hcB97KaKUp92KkJ6/3tFkv2p3wx/MeD8DZq4e6ZivuG/7jyRoLNFJ6r4KKzd+Oxd6z6kEBLtpLn0XBkx6rWsGzp5gnApbfbFlPdDIcgKCWNqTkZWuPL1nKQbzECovb2cHEE2KS9nnUIq+0PvkGh0X2P4c/77P4Agv/kEwfJJP2zMx9Bp6HdYDIi6/IldvScHKus1CRM3HKJs0Mo2s3okgj5X9NTZrZiI8M9tNaanvnESUkks5qpVtOpFzlCueFquwXbKyxN/oTgoRTmQN4mtb6X77XqT8mQKv5rfC3be6hmA1usBMwsDSM0/Zg3UKfaEMTXZfxq6vY2bPz9prbnXDV8I2m605vU2ReT0Y8FoAQzeTyy8JzY32cjnf7M+QWX9pfwjc9bQuUmUO6FwgdR72aOqFX1Y6phelwC1DSHk71X4wCbc+oVcZ2p/qtnuHt/yPeR3q0/NGXEH/dNRuKXWw4jll4cIHPeL1t1bR6ti+dWKiEZ1OpyO1Yk1fX7ccPgwuMMBYe+12KpeOiPPzaBCv+s19T1GKwpFBNQ67un8/+y6Cie8Sn3QjrpNgeOzcTVCGbqiPB5ReOGPt1J6IspUgG1CHqmilOJLlibA5rA2zEM5QqHglIpPrHwHMXNVrcwaCZvMRseRreSUo1qTzzBI3e7FAYWioMBEPupkKN9UDqvitC/umf3SCIoJdyB+YPF+Cf7CMF59l6Yirba17qZS93uhz/x89j7amuOJG6bGgsE6ZZo4sWJAv4pfVoP14dFYyk6E9Roqf+QWHVDnfpMsbzQcL95ev8oaLSRpnVTVKitmAWvoox5twvHQ/keXoJX3AQkmkmsd13+9xzffFQVvGz7qkk3koL1yyh1SyQgEXg5N/4ZZ1aOwVjDm5tLocpKlRM4Snh/2TrZgAIU9DylwVFr3+XnR3li1aMJoRVsiZT+QriavqWRzIkbEDk5rFwjcIrZqyTDAJIR7YhnsCR6aXaXsWnRWQSJiZw/rsRE0SyCSs10bRo1Q06MTF2J/MMQ=="},{"id":"7c85b76d-1a83-4bee-b42c-66966af08071","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"开发者指南","description":"developer-guide","prompt":"创建一份面向开发者的入门指南。指导新开发者如何设置本地开发环境,包括Go版本要求、依赖安装(通过go mod tidy)和数据库初始化。提供从克隆仓库到成功运行应用的完整步骤,涵盖使用build.sh脚本构建和使用go run main.go运行的方法。解释如何使用提供的Docker Compose文件进行本地测试。指南应包含调试技巧,例如如何启用pprof进行性能分析,以及如何理解main.go中的初始化流程。此外,提供一个简单的‘Hello World’级别的代码修改示例,比如如何添加一个新的健康检查API,以帮助开发者熟悉代码结构。最后,介绍如何运行测试套件(go test ./...)和查看覆盖率报告。","order":6,"progress_status":"completed","dependent_files":"build.sh,main.go,internal/utils/proxy_pool.go","gmt_create":"2025-10-08T20:04:49.4199566+08:00","gmt_modified":"2025-10-08T20:09:12.3147905+08:00","raw_data":"WikiEncrypted:F3QgleoEfoy16cQggYe9C5IaSqlGa9MAZLOFAWytoRMydW9CaKFacxmHFMFvq4MO4qJbomNzYz9hncXLdeBzq3fY6ynWvh0mBHFyX8UaL8b0wcWXSnuQ/e2L5ieDCeQZu4eHwClNmgAFFVxIE7fwq4P/L0Ouy8aZcek0QVX1T6OjcDp40oLyJS1lZWkB1MVrUI+5D4Rzp37Zb6zI+Z7GMLyfoDaNVlCuD8UMpYnMLTp6jym82WFZkCkD4xPJeB0MFTcG3qY2tIb5Bvvml7+yBuFFaIWKMSTNe8DNbKKSv1zzd7LWsXysYu48sFuNHIQl2narvUN8BeztzdNbnHeNafVTc6c558mr9U2RG1Ew6+zaIQ13J9VmLkDiNntBnxh1ug9tmnU//oO/P/XELKNI88btsp9+0VH3tljWocxnIg30WamPl1YDZ3v7njd60bFDOIyEJXwG4X6BcgKG8xc9hW1TTq/sqmzSng/sPGGAMPkH2PYUr2va7br7VORJP1uyyapNBLwIVKVnsldfKis7LHmYYoalh4+5X35XZJ8/vgj1NmCm7o4VzGj7gk8hlURFR1bQN4xEy9Tf67h6sMSkczXXl6YrftsVpaqhW14dfzNiKgYVHSAB+N/xNMPbilYCU2Vy4w03DHTZ2qDqmTyGalMZINYYEKdjXpWfuPTBFu/eK1FUfEW9IVY2jHkNBOaUNpwsY9WvHpirQPOXpIh0snPx/rL7520jLPYtjFXNCFKIrrzOpIMttjrvAxY7KRaY/otXIhRnTPT10NnT6Woo30DJRjtK6fpiTrQleDHYs4QhwzQLntO1XpQjRfkZvOHfQF6/mXE/FDvSZ2Eqm/sX8L+kJI5QPjI+ukL3Gc13zrsvCv9gEI3NAfl4hHpY1NoKijDd13GkskRlv6bXZvKy/WlfoZvqPzDENonheHr7Bywruul5cNFzsKeJ/RV7eNJcYelIpMxMU2IcyTwgEWjPrBqLGdxEFCKQ8LB+iPjazcE7qBVJspsHGnpYgaaJY5kMPHjP7tV1R4HlTg7kH0RlC8YWEiFDUAjKQr0NuJ+1pWPuFbBI89fgEOyObujf/16eblMfgE8ghCEyK+5QN7Gcj16rw55Y6i3gom+LRg7cFMCQAHgQna3BS9TO1NqGHNg4pTJh8+wLuCNa5U1v6Yrgo2Vjhwj/tHK4JDsSV11m8AraFoTXlxLYqcz0j+gLi1Rs3r9u6sxgjdnCO/AHKLg4dCY7FMO7sztU8rXzMEEyGXQWOGapCz5AjLOuYZ0RvvNkcJc6EtU4IELS2/piPGcJOk1jIFBLIlzPDVGMQZ21mBFPsN8i2jTa5TdvsnIClnnsL8wzJZ1FGgCTZ8MTW4wVWpAlTDLtxTPMeOAAeKcfFfQ="},{"id":"331580be-858a-4589-a919-b92058d006ec","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"第三方支付渠道集成","description":"supplier-integration","prompt":"创建一份详细的第三方支付渠道集成指南。以supplier_interface.go中定义的PayInterface为起点,解释开发者需要实现哪些方法(如Pay, QueryOrder)来集成一个新的支付供应商。通过分析apple.go和jd.go的具体实现,展示如何处理HTTP请求、解析响应、处理错误和实现重试逻辑。文档应指导开发者如何将新的供应商实现文件添加到third_party目录,并在系统中注册它。详细说明如何处理供应商特有的认证机制、API限流和数据格式。提供一个分步教程,从创建新的供应商结构体到编写单元测试(参考*_test.go文件)的完整过程。同时,讨论集成过程中的常见陷阱和最佳实践,例如如何保证交易的幂等性。","order":7,"progress_status":"completed","dependent_files":"internal/service/supplier/supplier_interface.go,internal/service/supplier/third_party/apple.go,internal/service/supplier/third_party/jd.go","gmt_create":"2025-10-08T20:04:49.4278395+08:00","gmt_modified":"2025-10-08T20:09:49.9517291+08:00","raw_data":"WikiEncrypted:ywogS1mtCJIl+oV7mNfjwB2ZQVNfkgJnqF/1L9l94PPI4nVaCUND6Ba/xPhgcy1ixLEENjLmt2SwM42O16RTFsyDUuIunmYOrznVtObrwE4CcrFFlAe52xCO6ES0KjMtkwt787qMvDW+cJKqvyTAFBojgcPuK3SDfK9Mec2DEpO1LfnYbqe9mqasmsSRhtAxiS60oBy5gyI4LL4kgv5l96szPTwtkZcGiZ+Ew5YDK+HRRh930XL4HBSoOo52r1VECCSez5WhwkfO4au7pSVeRrq8SRpbDnH5OaOe4oiHJk9au06vzz8NnjShH77ed/BKVPqC1nsRJxt2upXuX4zK8Eaph56pay4AMAGtd6d15+mqVcRcNhyWpNj6MmNtQv9gE7BuIn7nZor3PKc4v3rOGGRNlsa9khExQc/5CA6jhWlPiID+9fOlOqISgTivnhjNXiuAyEZgd53X7TDrPcjb8gPwWFX7g75dxn/9bfXFsfwBCtzHdl1/NvbNrZwSY0LxjjKSiqY47twiZp1UUG/8Epf9ykv0iGOcF9EuY4k5aUcTLMa2pikZymA2yBhnCXqdrLp8rHKyBLL/0jeMabvVGDrF+cwGKjQs54fQniOe30ijNO90Mu5Xhv0jyTFoDuZoRdnKMsFuBJDfOdW48OsDc6bXXy5ySH9Zoz5ggXZQ3AVwG+1MDG/2dJ30hRSmpURyY91k07LxX5j7lHaxvdKHUozGcJJmT7elY7WJlWg6n45AYSpytJ7zrMSZCm8+hWYHvbRE7MNOggcdoAbpbL2R5V/jR2g/0HLCI8cbXgsAvEJDhWgdcKxw+yd5hbLeNhTFMzkTqGeCP/AL+4ePNQn9xinm8tEc2IBPlLxPWff5Bx3daE3u0gz1E0aPbF2mKp52xV5l27W4/XviATRAoyyol5CREMVn1qxkSQ34IEto3dUqr2q4BVFKnXfzzbuhnFe9wDuTIyqzQ8f7vycmn9F3B5GBAdHKVhkEZ9w+IfbYJB2kOyETLYtsP8mtWAyh3xz5HS/U9OXIajAOQmGszeqnoenAh9REhMe6zuj35fC6+/7gqduAjJ/aA/8xgWiaNCovrrMfXwU76yCRLuqg9bBJ9RsdY8xqnuqJE4i+XZUueq9d65kKFpInLchwpL2EETEKmNpBuUAniUOWoOe6RDNitu8ODD5YbYKukPzvHwq6NhH2+xK0JKXb7jWsytKOejz+BQ/HpB9b5ds7ysGL/z68X0QMNrykSZNc55DM+RxJ527isaTQD4Lb99xas6cHEDsDLbaRqFtX965E+fXGU9xunmtCdMtB0fJLfYgdrV/wQZNQ9k2hTTrRAEetYOL0/iSpsDnBQK9VSjQ2hTb297pPD9YadKQ2tfF39C+GFDgWTSUGUPjDvjWNVURGlNEorXhTGydT04HDQMq9DuKzJqxdbEeDrNisQFzpWY4hdzx6oBDRzW5v9k0pmFYmaI71S3WTKc1VGp3zgEJqBL3LWfnD/kQ7oUJOs8KD5QMBLSNg7vadyzFL5t+edYSy/0uG4OQk7/Jsmv9jmFsqkJCoFdLMoSfwOEEz61PNZm5qdmD9E3uUnR6KDx7Iri3bDtw3VwhS"},{"id":"5103593b-a8d6-47a1-893e-70804c5aece3","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"监控与故障排除","description":"monitoring-troubleshooting","prompt":"创建监控和故障排除指南。解释如何利用OpenTelemetry(otelTrace包)进行分布式追踪,包括如何查看和分析调用链路,以及如何利用日志(logs.go)进行问题诊断。说明系统生成的关键指标(metrics)和如何通过Prometheus进行收集。提供一个常见问题列表,例如支付请求超时、回调失败、数据库连接池耗尽等,并给出详细的排查步骤和解决方案。指导开发者如何使用测试文件(如pay_solve_test.go)来复现和修复问题。文档还应涵盖性能监控,如如何识别慢查询和高延迟的API端点,并提供优化建议。最后,说明如何配置告警规则以及时发现系统异常。","order":8,"progress_status":"completed","dependent_files":"internal/otelTrace/init.go,internal/otelTrace/logs.go,internal/service/pay_solve_test.go","gmt_create":"2025-10-08T20:04:49.4359827+08:00","gmt_modified":"2025-10-08T20:09:55.1250682+08:00","raw_data":"WikiEncrypted:HL3VqGjXq8A3aGeLxAjVPseClgy+ysLjZsoexAfPX3D+iOtNevnlQtZ/dd7X4on1/Fyf+3QZwDuK3nCfC7OOkg86/p0JWgywkQarmHhcigUgldYHYgPlswdqtUiJ71c2S+Gi4+wXeIwcNjykzkwdznLlXNcmVsr1v+p768Zyqop5mDO8xnxo+XQBHtJ3YXCOljmnoJXjrC3ZNNtCYt+KHXxwijCvLJnkvhAeXKn2MpU2qxKKneMv/5/xOC4nYR1g3yi0czu0l70Sc+SVwlXl1XJ57EccIG85G06Ky1blzAaQtrV9k9tyKYV3GuWX30m8MNQS+eTO/O6Cj/tu+oitNGS5ATfwtsWcv4k5ZgeHbWOrx/OnQQEdrw9VYm9aBtkmmBzfg256bR+j3pkRtz4gf9R2ANU5iozq9EJHUoRb2l9xy3Tez8lILslubKwODlRiP40RRAmy4fVQTSfGwiVA0kCVxlb4NCqisrIYzmSmryK9AbZJUR7UZ1gKn6rltyP4OpamSFle5UrthA0CVGZKxpCSFUu43Vx0/K7bOz94BThDgparsv3hko5xVsWb62yce2lK1xTdrjMaVwPsYwD//Wme/bKI0RJqRgSaKWguYPlNMcVFe/nBqUl/f9fS2ni87qSX4Qt1wbk5Jbm8wygD5GuXDygRVTc27t6udRhZ3l3iY/9XHmUdCDfeYtUeyB0eyJAVE/iYu/xngnYkZPWcsngoo1zJGz+Sl1TrkmQYCRlkUtJpqo5ekNSf1q9Oi5/HZK6qgHHggDmrkr7ikiGIjz8fDvPpmk4GGGOKsnmyn9gEGvHgXb8S1ZOVXyL03Hyq0FK4azgII7hV2IM3BEzOL1hP2oIGGtLaqXISqvF2llfFL7WyHU98ET/YNgvenhdF4/HIx/K1wAmmtsmpepTd2gO/TQEDgigicw1PENvvfVcsfgXJrb9PH1psCfkkXepk2rx04OI8X9Q8csBVtfMfqZiOwnI/H+zZ+U+tdopVwPeHohjLgpoOXlgHQUYqclbISkvFqQnll8bEQaQgiAczs4TEH4lKKeKKHoO3qKH5KkYhqILXKT8FIfwTIoiskg/i+rDcZ8tDR19Hb+vLkDbbA59Bh0RzLwJzNPbcU4Hodjg/5MvSkc9ZXAFrbu3f9Mw+1QmC1y1fu0M9PuGMI367bU0yBbiGis4BAjOBb8GnLxmtifOnd+58XC7X32FyIdQOjoG+1UUlDQ9FzuLoDXxHuXa06LYt0i2fd6qkAzH0ETXaevaA5h5jHR74NAEJGKtoBVfezd4cDoVyUkv9OQq/zzUwqNMr2ys0AndefGVHqCp5n3xszeLwYL3TNzeovTq867z+h0+MUeOvupXt3gh6Q24BKxBVLjN9n0ciQaTD9NT1Q4nFMv3TrGD+YptlHFkBTDjYJQk8FnRTPfJ+96Xst/ni6IWFMND0a2bLTLtWY9w="}],"wiki_items":[{"catalog_id":"3f5378b4-a8c2-4361-90a2-caf79aeba7fb","title":"项目概述","description":"project-overview","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"a9f244fa-cb21-4a31-85c5-74ee22535241","gmt_create":"2025-10-08T20:07:08.6767978+08:00","gmt_modified":"2025-10-08T20:07:08.6884683+08:00"},{"catalog_id":"80fb1e42-5bd2-4870-8b88-77d31ff5c478","title":"API参考","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"89d888b3-2b22-4be7-8c3e-66e1f9cef86c","gmt_create":"2025-10-08T20:07:10.9494972+08:00","gmt_modified":"2025-10-08T20:07:10.9680712+08:00"},{"catalog_id":"576b2803-bcc0-4769-89b3-54c89e6b7381","title":"技术栈与依赖","description":"technology-stack","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"013b2790-e5e2-4879-8a97-c5dee7adde89","gmt_create":"2025-10-08T20:08:07.0438986+08:00","gmt_modified":"2025-10-08T20:08:07.1467933+08:00"},{"catalog_id":"1ccdc69d-fc3b-4d08-9be6-169095e4a163","title":"核心架构","description":"core-architecture","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"7424e713-8de3-415b-ab24-f02a1102bdbc","gmt_create":"2025-10-08T20:08:12.4384285+08:00","gmt_modified":"2025-10-08T20:08:12.4586942+08:00"},{"catalog_id":"a5d56738-c20f-4178-9f81-d01bb592f194","title":"数据模型","description":"data-model","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"6e2e98a9-36f3-46c1-b2f2-db52c4526f11","gmt_create":"2025-10-08T20:08:34.0144975+08:00","gmt_modified":"2025-10-08T20:08:34.0353959+08:00"},{"catalog_id":"53d903ba-6508-45b8-b48b-b3d00d3ed07a","title":"部署与配置","description":"deployment-configuration","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"d2d80765-26c3-4c0b-a302-612693077838","gmt_create":"2025-10-08T20:08:54.4805496+08:00","gmt_modified":"2025-10-08T20:08:54.491486+08:00"},{"catalog_id":"7c85b76d-1a83-4bee-b42c-66966af08071","title":"开发者指南","description":"developer-guide","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"87ee006d-1361-4097-943f-fd617b437f89","gmt_create":"2025-10-08T20:09:12.3048385+08:00","gmt_modified":"2025-10-08T20:09:12.3157912+08:00"},{"catalog_id":"331580be-858a-4589-a919-b92058d006ec","title":"第三方支付渠道集成","description":"supplier-integration","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"3f94dede-2298-4788-89a2-f4b817701e01","gmt_create":"2025-10-08T20:09:49.9419345+08:00","gmt_modified":"2025-10-08T20:09:49.9524517+08:00"},{"catalog_id":"5103593b-a8d6-47a1-893e-70804c5aece3","title":"监控与故障排除","description":"monitoring-troubleshooting","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"77d3b3e8-3b5b-4065-a83c-cda3fa14b5b5","gmt_create":"2025-10-08T20:09:55.116388+08:00","gmt_modified":"2025-10-08T20:09:55.1261123+08:00"},{"catalog_id":"ff8a9c9d-2dc0-433a-a1d4-b84ee2141635","title":"订单模型","description":"order-model","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"302aea38-1949-48e6-bd95-96cb17b84d12","gmt_create":"2025-10-08T20:10:13.3069178+08:00","gmt_modified":"2025-10-08T20:10:13.3189892+08:00"},{"catalog_id":"3d1b720f-a641-456e-94d0-ff9db2b5568c","title":"Docker部署指南","description":"docker-deployment","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"3f30d007-e6cc-4636-8ab7-f10562baff6a","gmt_create":"2025-10-08T20:10:46.0191897+08:00","gmt_modified":"2025-10-08T20:10:46.0290875+08:00"},{"catalog_id":"0fd4a109-43f9-4cea-9416-4cd2bcafd325","title":"支付API","description":"payment-api","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"0fb51e95-8a1d-45fe-96b2-632c00da5541","gmt_create":"2025-10-08T20:10:53.9304568+08:00","gmt_modified":"2025-10-08T20:10:53.9579352+08:00"},{"catalog_id":"a21144d5-112d-4642-a874-64fb8a1ea84f","title":"Beego 框架集成","description":"beego-framework","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"13bd83fa-402e-438b-a012-6d53eac7c39d","gmt_create":"2025-10-08T20:11:20.9462141+08:00","gmt_modified":"2025-10-08T20:11:20.9577989+08:00"},{"catalog_id":"7cc42a3a-553a-4702-9eaf-b76dd3628a17","title":"支付服务架构","description":"payment-service-architecture","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"026c8458-a7b5-44cf-b052-10b1cd6604f2","gmt_create":"2025-10-08T20:11:36.0414447+08:00","gmt_modified":"2025-10-08T20:11:36.0519241+08:00"},{"catalog_id":"062cb25b-369d-43d0-b6d3-96447d99b3e9","title":"商户模型","description":"merchant-model","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"b527099a-0510-438d-a4ec-b8ed8642ae8e","gmt_create":"2025-10-08T20:11:59.3046725+08:00","gmt_modified":"2025-10-08T20:11:59.3164336+08:00"},{"catalog_id":"fd2a2cba-0887-44b8-93c2-9cc9e520daae","title":"OpenTelemetry 分布式追踪","description":"opentelemetry-tracing","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"d0e098cc-486d-48ae-99b6-dae8bd81b609","gmt_create":"2025-10-08T20:12:14.104241+08:00","gmt_modified":"2025-10-08T20:12:14.1189211+08:00"},{"catalog_id":"c7928cce-8e94-4629-be4d-3af7f5d251bb","title":"查询API","description":"query-api","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"75b363d5-4074-4921-9ada-579b8f5a30c4","gmt_create":"2025-10-08T20:12:22.877929+08:00","gmt_modified":"2025-10-08T20:12:22.8891039+08:00"},{"catalog_id":"74304c2d-414f-40ca-9155-fde8c06a0128","title":"配置文件详解","description":"configuration-file","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"3b453233-b2ab-4942-9a6c-d92a5a3897c0","gmt_create":"2025-10-08T20:12:50.0833468+08:00","gmt_modified":"2025-10-08T20:12:50.0945204+08:00"},{"catalog_id":"316c7f5b-5e53-4322-9376-f94f1cc1ba37","title":"账户与代理商模型","description":"account-agent-model","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"f5af27a6-1bd2-4346-a7a8-2682705f09c5","gmt_create":"2025-10-08T20:13:19.8684904+08:00","gmt_modified":"2025-10-08T20:13:19.8881676+08:00"},{"catalog_id":"0d7875e0-1107-4966-8a99-a6d24685c88c","title":"供应商集成架构","description":"supplier-integration-architecture","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"16f1ef56-d692-41dd-84d7-c41790f98abb","gmt_create":"2025-10-08T20:13:46.8661406+08:00","gmt_modified":"2025-10-08T20:13:46.8783305+08:00"},{"catalog_id":"715db9db-8d32-4ea3-926a-b56c98ea6d8d","title":"数据库与缓存系统","description":"database-cache","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"8a821f9b-5ad9-4602-96c2-724299a01a8b","gmt_create":"2025-10-08T20:14:05.025848+08:00","gmt_modified":"2025-10-08T20:14:05.0416874+08:00"},{"catalog_id":"8600f0c5-e3cf-489b-a029-725506750564","title":"代付API","description":"payfor-api","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"5c05b03a-d7c9-43f5-94c6-1f4ea2793f19","gmt_create":"2025-10-08T20:14:21.0044301+08:00","gmt_modified":"2025-10-08T20:14:21.021717+08:00"},{"catalog_id":"3f59a04d-339e-40c5-8c7f-c98ed6ef6d8b","title":"环境变量管理","description":"environment-variables","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"93cae8db-9a04-407a-8446-250cdc33f661","gmt_create":"2025-10-08T20:14:26.0779486+08:00","gmt_modified":"2025-10-08T20:14:26.0886312+08:00"},{"catalog_id":"c0f73068-9c54-4cc7-ae03-811f69af12c9","title":"消息队列与异步处理","description":"message-queue","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"3077240f-f00b-4f59-a8ce-8991408c4b96","gmt_create":"2025-10-08T20:15:18.9536664+08:00","gmt_modified":"2025-10-08T20:15:18.9619544+08:00"},{"catalog_id":"8af4b541-5a66-4fb9-86b1-7c95c9f63ab0","title":"任务调度架构","description":"task-scheduling-architecture","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"f0a4a14b-8948-4372-a8b7-6974e4286083","gmt_create":"2025-10-08T20:15:38.5917719+08:00","gmt_modified":"2025-10-08T20:15:38.6066131+08:00"},{"catalog_id":"15483189-42f7-4bbe-89bd-55f035c33ccf","title":"回调API","description":"callback-api","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"70b6c90d-240f-4eb3-abc6-50fb7add6fc3","gmt_create":"2025-10-08T20:15:38.799372+08:00","gmt_modified":"2025-10-08T20:15:38.8103294+08:00"},{"catalog_id":"18826686-b467-4bd9-879d-73a780854d0f","title":"MySQL数据库集成","description":"database-mysql","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"9c7904f8-0b4a-422b-806d-55c96bec2fe6","gmt_create":"2025-10-08T20:16:01.6742931+08:00","gmt_modified":"2025-10-08T20:16:01.6864756+08:00"},{"catalog_id":"0ebb9117-99a5-4092-862c-49ee70ccfee0","title":"初始化与资源配置","description":"opentelemetry-tracing-initialization","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"b5f75438-5c24-4f0f-be95-f857806fcfaf","gmt_create":"2025-10-08T20:16:13.1207896+08:00","gmt_modified":"2025-10-08T20:16:13.131653+08:00"},{"catalog_id":"7f560146-d4af-4131-8722-dcf698604b6f","title":"Redis缓存系统","description":"cache-redis","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"2500aa21-fe32-4057-a5ad-11fbd4d19546","gmt_create":"2025-10-08T20:16:35.7490861+08:00","gmt_modified":"2025-10-08T20:16:35.7602342+08:00"},{"catalog_id":"b99f6bc9-1a5f-4e15-82c4-3f4c27eb0724","title":"HTTP中间件集成","description":"opentelemetry-tracing-middleware","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"4a9995be-1002-4a48-bf07-8b4f725756d0","gmt_create":"2025-10-08T20:16:57.8698101+08:00","gmt_modified":"2025-10-08T20:16:57.8804333+08:00"},{"catalog_id":"40a4568f-d8f6-46e2-a301-107062e68778","title":"Span生命周期管理","description":"opentelemetry-tracing-span-management","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"b2cf330f-309b-4fa5-980c-c5809a143195","gmt_create":"2025-10-08T20:17:08.3980224+08:00","gmt_modified":"2025-10-08T20:17:08.4091288+08:00"},{"catalog_id":"556f07d5-845b-4291-9b39-b0872940a3a8","title":"日志与追踪上下文关联","description":"opentelemetry-tracing-logging-integration","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"047d142f-ec46-4f80-83d3-c377a86858b8","gmt_create":"2025-10-08T20:17:17.7986613+08:00","gmt_modified":"2025-10-08T20:17:17.8131445+08:00"},{"catalog_id":"00f89107-2ade-477a-b10e-0c444161fdbb","title":"资源标识与上下文配置","description":"opentelemetry-tracing-resource","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"e50eff25-5123-4c73-8a3b-487293043f2f","gmt_create":"2025-10-08T20:17:55.1005301+08:00","gmt_modified":"2025-10-08T20:17:55.1156575+08:00"},{"catalog_id":"a85503ac-22f7-4a7c-946f-359954121de8","title":"追踪导出器配置","description":"opentelemetry-tracing-exporter","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"ed7bbb93-3e0c-49fe-b1dd-a92d8176638e","gmt_create":"2025-10-08T20:17:57.5755162+08:00","gmt_modified":"2025-10-08T20:17:57.5865498+08:00"},{"catalog_id":"1fedbb41-1015-4ec4-aaa3-c732e30b12f6","title":"采样策略与批量处理","description":"opentelemetry-tracing-sampling","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"243ba92b-7b56-4596-9c54-31905f65e471","gmt_create":"2025-10-08T20:18:01.3341913+08:00","gmt_modified":"2025-10-08T20:18:01.34411+08:00"},{"catalog_id":"25edcf0d-932e-4a7e-ac78-00f9888b6ac7","title":"分布式上下文传播","description":"opentelemetry-tracing-propagation","extend":"{}","progress_status":"completed","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593","id":"99e9dc6d-e943-4712-a961-7a053872ad8f","gmt_create":"2025-10-08T20:18:48.5863741+08:00","gmt_modified":"2025-10-08T20:18:48.5968345+08:00"}],"wiki_overview":{"content":"\u003cblog\u003e\n# Kami Gateway 项目综合分析\n\n## 1. 项目介绍\n\nKami Gateway 是一个基于 Go 语言开发的高性能支付网关服务,旨在为多商户、多通道的聚合支付场景提供稳定可靠的解决方案。该项目主要处理第三方卡密充值、订单调度、代付请求及回调通知等核心业务,支持爱博、京东卡、天猫游戏、沃尔玛等数十种第三方支付渠道。\n\n项目的核心目标是构建一个高可扩展性、高稳定性的支付网关系统,通过微服务架构实现业务解耦,利用 Beego 框架作为 Web 服务基础,并结合 Redis、RabbitMQ 等中间件实现任务队列与异步处理机制。系统集成了 OpenTelemetry 实现分布式追踪,具备良好的可观测性与运维能力。\n\n本项目主要面向支付平台开发者、系统架构师以及需要集成多种支付渠道的商户技术团队,适用于需要处理大量支付交易、要求高可用性和可扩展性的商业场景。\n\n## 2. 技术架构\n\n### 组件分解\n\nKami Gateway 采用分层架构设计,主要包括以下几个核心组件:\n\n- **API 层**:处理 HTTP 请求,提供 RESTful API 接口\n- **业务逻辑层**:实现核心支付业务逻辑,包括订单处理、支付回调等\n- **服务层**:封装第三方支付渠道的具体实现\n- **数据访问层**:与 MySQL、Redis 等数据存储系统交互\n- **基础设施层**:提供缓存、消息队列、分布式追踪等公共服务\n\n### 设计模式\n\n项目采用了多种设计模式来提高代码的可维护性和扩展性:\n\n- **依赖注入**:通过初始化函数注入配置、缓存、消息队列等依赖\n- **单例模式**:用于管理队列管理器、代理池等全局资源\n- **事件驱动**:通过事件总线实现订单创建、处理、失败等事件的发布与订阅\n- **工厂模式**:用于创建不同类型的任务处理器\n\n### 系统关系与数据流\n\n```mermaid\nflowchart TD\n A[客户端] --\u003e B[API 层]\n B --\u003e C[业务逻辑层]\n C --\u003e D[服务层]\n D --\u003e E[第三方支付渠道]\n C --\u003e F[数据访问层]\n F --\u003e G[(MySQL)]\n F --\u003e H[(Redis)]\n I[第三方渠道] --\u003e J[回调处理]\n J --\u003e C\n K[RabbitMQ] --\u003e L[异步任务处理]\n L --\u003e C\n M[OpenTelemetry] --\u003e N[分布式追踪]\n N --\u003e C\n N --\u003e D\n```\n\n## 3. 关键实现\n\n### 主要入口点\n- [main.go](e:\\projects\\kami\\kami_gateway\\main.go)\n\n### 核心模块\n- [router.go](e:\\projects\\kami\\kami_gateway\\internal\\routers\\router.go)\n- [pool/service.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\pool\\service.go)\n- [queue/manager.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\queue\\manager.go)\n- [order_notify.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\notify\\order_notify.go)\n\n### 配置方法\n- [app.conf](e:\\projects\\kami\\kami_gateway\\conf\\app.conf)\n\n### 外部依赖\n- [init.go](e:\\projects\\kami\\kami_gateway\\internal\\otelTrace\\init.go)\n\n### 集成点\n- [aibo.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\aibo.go)\n- [jd.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\jd.go)\n- [apple.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\apple.go)\n- [walmart.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\walmart.go)\n\n### 组件关系图\n\n```mermaid\ngraph LR\n A[main.go] --\u003e B[router.go]\n A --\u003e C[app.conf]\n A --\u003e D[init.go]\n B --\u003e E[控制器]\n E --\u003e F[service]\n F --\u003e G[第三方支付实现]\n G --\u003e H[第三方渠道]\n F --\u003e I[数据访问]\n I --\u003e J[MySQL]\n I --\u003e K[Redis]\n D --\u003e L[OpenTelemetry]\n L --\u003e A\n L --\u003e F\n L --\u003e G\n```\n\n## 4. 关键特性\n\n### 功能概述\n\nKami Gateway 提供了完整的支付网关功能,包括:\n- 多渠道支付支持\n- 动态代理池\n- 异步任务队列\n- 自动订单调度\n- 分布式追踪\n- 灵活配置\n- Docker 化部署\n- API 回调处理\n\n### 实现亮点\n\n项目通过创新的订单池机制实现了高效的订单匹配和处理。订单池服务(OrderPoolService)作为核心组件,负责管理用户订单和生产订单的匹配过程。系统采用事件驱动模型,通过事件总线(EventBus)实现订单创建、处理、失败等事件的发布与订阅,确保了系统的松耦合和高可扩展性。\n\n异步任务处理通过 RabbitMQ 实现,订单回调消费者(CreateOrderNotifyConsumer)监听消息队列,处理订单回调任务。系统还实现了智能的重试机制,根据回调次数动态调整重试间隔,提高了系统的稳定性和可靠性。\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e 初始化\n 初始化 --\u003e 运行中: 启动服务\n 运行中 --\u003e 处理订单: 接收订单请求\n 处理订单 --\u003e 匹配订单: 进入订单池\n 匹配订单 --\u003e 提交订单: 找到匹配\n 提交订单 --\u003e 等待回调: 发送至第三方\n 等待回调 --\u003e 更新状态: 收到回调\n 更新状态 --\u003e 通知商户: 发送通知\n 通知商户 --\u003e 运行中: 完成\n 匹配订单 --\u003e 超时处理: 未找到匹配\n 超时处理 --\u003e 运行中: 清理订单\n 提交订单 --\u003e 提交失败: 提交错误\n 提交失败 --\u003e 重试提交: 重新提交\n 重试提交 --\u003e 提交订单: 重试\n 重试提交 --\u003e 运行中: 达到最大重试次数\n```\n\u003c/blog\u003e","gmt_create":"2025-10-08T20:03:05.5426812+08:00","gmt_modified":"2025-10-08T20:03:05.5426812+08:00","id":"3df72775-b038-40a3-82fb-11672047d8a7","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593"},"wiki_readme":{"content":"# Kami Gateway\n\nKami Gateway 是一个基于 Go 语言开发的高性能支付网关服务,主要用于处理第三方卡密充值、订单调度、代付请求及回调通知等核心业务。项目采用 Beego 框架作为 Web 服务基础,并结合 Redis、RabbitMQ 等中间件实现任务队列与异步处理机制。系统支持多种第三方支付渠道(如爱博、京东卡、天猫游戏、沃尔玛等),具备高可扩展性与稳定性,适用于多商户、多通道的聚合支付场景。\n\n本项目使用 OpenTelemetry 实现分布式追踪,集成 Redis 缓存与代理池机制,通过微服务架构实现解耦,具备良好的可观测性与运维能力。\n\n## 主要特性\n\n- **多渠道支付支持**:支持爱博、京东、天猫、沃尔玛、六盒、茄子、金科、善付、鲁班等数十种第三方卡密充值渠道。\n- **动态代理池**:内置代理调度机制,支持 HTTP 代理轮询,提升请求成功率。\n- **异步任务队列**:基于 Redis 实现任务队列,支持卡密提交、登录、查询等异步任务处理。\n- **自动订单调度**:通过事件驱动模型实现订单创建、查询、超时处理等自动化流程。\n- **分布式追踪**:集成 OpenTelemetry,支持链路追踪与日志关联,便于问题排查。\n- **灵活配置**:通过 `app.conf` 配置文件管理数据库、MQ、第三方接口等参数。\n- **Docker 化部署**:提供完整的 Dockerfile 与 docker-compose 配置,支持本地与生产环境快速部署。\n- **API 回调处理**:统一接收各渠道的支付结果回调,自动更新订单状态并通知商户。\n\n## 安装与部署\n\n### 前置依赖\n\n- Go 1.24+\n- Redis\n- MySQL\n- RabbitMQ\n- Docker(可选)\n\n### 构建方式\n\n```bash\n# 构建二进制文件\n./build.sh\n```\n\n### Docker 部署\n\n```bash\n# 构建并启动服务(生产环境)\ndocker-compose up -d\n\n# 本地开发环境启动\ndocker-compose -f docker-compose-local.yaml up -d\n```\n\n### 配置说明\n\n主要配置文件位于 `conf/app.conf`:\n\n```ini\nappname = jhgateway\nhttpport = 12309\nrunmode = prod\n\n[mysql]\ndbhost = 127.0.0.1\ndbport = 3306\ndbuser = root\ndbpasswd = Woaizixkie!123\ndbbase = kami\n\n[redis]\nhost = 127.0.0.1:6379\npassword = \"\"\n\n[mq]\nhost = 127.0.0.1\nport = 61613\n```\n\n第三方接口地址、密钥等配置也在此文件中定义,如 `mf`, `appleCard`, `jdCard` 等。\n\n## 使用方法\n\n### API 接口\n\n通过 `internal/routers/router.go` 可知主要 API 路由如下:\n\n| 路径 | 方法 | 功能 |\n|------|------|------|\n| `/gateway/scan` | POST | 创建充值订单 |\n| `/gateway/queryAccountInfo/:channel` | GET | 查询账户信息 |\n| `/gateway/createOrder` | POST | 创建订单 |\n| `/gateway/merchant/query` | POST | 商户查单 |\n| `/gateway/supplier/order/query` | POST | 上游订单查询回调 |\n| `/gateway/update/order` | POST | 更新订单状态 |\n\n### 第三方回调\n\n系统接收来自各渠道的支付结果回调,路径如下:\n\n- `/mfcard/notifyV2` → MF卡\n- `/appleCard/notify` → 苹果卡\n- `/jdCard/notify` → 京东卡\n- `/tMallGame/notify` → 天猫游戏\n- `/walMart/notify` → 沃尔玛\n- `/sixFat/notify` → 六盒\n- `/AiBo/notify` → 爱博\n- ...(其他渠道类似)\n\n回调处理逻辑由 `internal/service/supplier/third_party/*.go` 实现,如 `aibo.go`、`jd.go` 等。\n\n### 任务队列机制\n\n系统通过 Redis 实现任务队列,核心组件位于:\n\n- `internal/service/supplier/third_party/queue/`:队列管理、任务定义、处理器\n- `internal/service/supplier/third_party/pool/`:工作池、事件处理、通道实现\n\n任务类型包括:\n- `card_submit`:卡密提交\n- `login`:登录任务\n- `card_query`:卡密查询\n\n通过 `QueueManager` 动态创建通道队列,支持按 `channelID` 隔离任务流。\n\n## 开发说明\n\n### 项目结构\n\n```\n├── conf/ # 配置文件\n├── deploy/ # 部署脚本与Docker配置\n├── internal/ # 核心业务逻辑\n│ ├── cache/ # Redis缓存封装\n│ ├── config/ # 配置读取\n│ ├── controllers/ # HTTP控制器\n│ ├── models/ # 数据模型\n│ ├── routers/ # 路由注册\n│ ├── service/ # 业务服务\n│ │ └── supplier/ # 第三方渠道实现\n│ ├── utils/ # 工具函数(加密、签名、HTTP等)\n│ └── otelTrace/ # 分布式追踪\n├── build.sh # 构建脚本\n└── main.go # 入口文件\n```\n\n### 添加新支付渠道\n\n1. 在 `internal/service/supplier/third_party/` 下创建新实现,如 `mycard.go`\n2. 实现 `SendCard`、`Scan`、`PayNotify` 方法\n3. 在 `router.go` 中注册回调路由\n4. 在配置文件中添加接口地址与密钥\n\n### 日志与追踪\n\n日志输出至 `./logs/jhmerchant.log`,支持分级输出(debug ~ emergency)。 \n通过 OpenTelemetry 支持链路追踪,可在日志中查看 `trace_id`、`span_id` 进行关联分析。\n\n## 许可证\n\n未找到 LICENSE 文件,许可证信息暂缺。","gmt_create":"2025-08-22T11:07:51.6280873+08:00","gmt_modified":"2025-08-22T11:07:51.6280873+08:00","id":"e8a20657-bb01-4b74-bd31-67bf99ba82a3","repo_id":"154b5d19-4920-4fbb-b73a-e2620e744593"},"wiki_repo":{"id":"154b5d19-4920-4fbb-b73a-e2620e744593","name":"kami_gateway","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── conf\\n│ └── app.conf\\n├── deploy\\n│ ├── Dockerfile\\n│ ├── docker-compose-local.yaml\\n│ ├── docker-compose.yaml\\n│ └── wait-for-it.sh\\n├── internal\\n│ ├── cache\\n│ │ ├── lock.go\\n│ │ ├── options.go\\n│ │ ├── redis.go\\n│ │ └── redis_test.go\\n│ ├── config\\n│ │ ├── cfg_model.go\\n│ │ ├── config.go\\n│ │ ├── mq_config.go\\n│ │ └── proxy.go\\n│ ├── consts\\n│ │ ├── road_info.go\\n│ │ └── steal_rule.go\\n│ ├── controllers\\n│ │ ├── base_controller.go\\n│ │ ├── order_controller.go\\n│ │ ├── payfor_controller.go\\n│ │ └── scan_controller.go\\n│ ├── dto\\n│ │ ├── order.go\\n│ │ └── order_test.go\\n│ ├── models\\n│ │ ├── accounts\\n│ │ │ ├── account.go\\n│ │ │ └── account_history_info.go\\n│ │ ├── agent\\n│ │ │ ├── agent_info.go\\n│ │ │ └── agent_profit.go\\n│ │ ├── hidden\\n│ │ │ ├── merchant_hidden_config.go\\n│ │ │ └── merchant_hidden_record.go\\n│ │ ├── merchant\\n│ │ │ ├── merchant_info.go\\n│ │ │ └── merchant_load_info.go\\n│ │ ├── merchant_deploy\\n│ │ │ └── merchant_deploy_info.go\\n│ │ ├── notify\\n│ │ │ └── notify_info.go\\n│ │ ├── order\\n│ │ │ ├── order_info.go\\n│ │ │ ├── order_profit_info.go\\n│ │ │ ├── order_settle_info.go\\n│ │ │ └── platform_profit.go\\n│ │ ├── payfor\\n│ │ │ └── payfor_info.go\\n│ │ ├── response\\n│ │ │ └── response.go\\n│ │ ├── road\\n│ │ │ ├── road_info.go\\n│ │ │ └── road_pool_info.go\\n│ │ ├── setting\\n│ │ │ └── sys_config_dict.go\\n│ │ ├── supply_model\\n│ │ │ └── models.go\\n│ │ ├── system\\n│ │ │ ├── bank_card_info.go\\n│ │ │ ├── menu_info.go\\n│ │ │ ├── power_info.go\\n│ │ │ ├── role_info.go\\n│ │ │ └── second_menu_info.go\\n│ │ ├── task\\n│ │ │ └── task.go\\n│ │ ├── user\\n│ │ │ └── user_info.go\\n│ │ └── init.go\\n│ ├── otelTrace\\n│ │ ├── circuit_breaker.go\\n│ │ ├── consts.go\\n│ │ ├── init.go\\n│ │ ├── link_ctx_test.go\\n│ │ ├── logs.go\\n│ │ ├── middleware.go\\n│ │ ├── simple.go\\n│ │ ├── span.go\\n│ │ └── utils.go\\n│ ├── proxy\\n│ │ ├── config.go\\n│ │ ├── example.go\\n│ │ ├── init.go\\n│ │ └── proxy_pool.go\\n│ ├── routers\\n│ │ └── router.go\\n│ ├── schema\\n│ │ ├── query\\n│ │ │ ├── merchant_query.go\\n│ │ │ ├── payfor_query.go\\n│ │ │ └── supplier_query.go\\n│ │ ├── request\\n│ │ │ ├── accountInfo.go\\n│ │ │ ├── order.go\\n│ │ │ └── order_test.go\\n│ │ └── response\\n│ │ ├── common.go\\n│ │ ├── pay_resp.go\\n│ │ └── payfor_resp.go\\n│ ├── service\\n│ │ ├── backend\\n│ │ │ ├── backend.go\\n│ │ │ └── backend_test.go\\n│ │ ├── client\\n│ │ │ ├── heepay.go\\n│ │ │ ├── models.go\\n│ │ │ ├── ocr.go\\n│ │ │ ├── ocr_test.go\\n│ │ │ └── resender.go\\n│ │ ├── message\\n│ │ │ ├── init.go\\n│ │ │ └── send_message.go\\n│ │ ├── notify\\n│ │ │ ├── order_notify.go\\n│ │ │ └── order_notify_test.go\\n│ │ ├── pay_for\\n│ │ │ ├── payfor_service.go\\n│ │ │ └── payfor_solve.go\\n│ │ ├── supplier\\n│ │ │ ├── t_mall_game\\n│ │ │ │ └── t_mall_game.go\\n│ │ │ ├── third_party\\n│ │ │ │ ├── pool\\n│ │ │ │ │ ├── card_sender\\n│ │ │ │ │ │ ├── careless.go\\n│ │ │ │ │ │ ├── careless_test.go\\n│ │ │ │ │ │ ├── eggplant.go\\n│ │ │ │ │ │ ├── eggplant_test.go\\n│ │ │ │ │ │ ├── enums.go\\n│ │ │ │ │ │ ├── fat_six.go\\n│ │ │ │ │ │ ├── fat_six_test.go\\n│ │ │ │ │ │ ├── favorable_clouds.go\\n│ │ │ │ │ │ ├── favorable_clouds_test.go\\n│ │ │ │ │ │ ├── flyfish.go\\n│ │ │ │ │ │ ├── flyfish_test.go\\n│ │ │ │ │ │ ├── flyfishv2.go\\n│ │ │ │ │ │ ├── flyfishv2_test.go\\n│ │ │ │ │ │ ├── jinke.go\\n│ │ │ │ │ │ ├── jinke_test.go\\n│ │ │ │ │ │ ├── luban.go\\n│ │ │ │ │ │ ├── luban_test.go\\n│ │ │ │ │ │ ├── magic_fish.go\\n│ │ │ │ │ │ ├── magic_fish_test.go\\n│ │ │ │ │ │ ├── models.go\\n│ │ │ │ │ │ ├── myself.go\\n│ │ │ │ │ │ ├── nuclear.go\\n│ │ │ │ │ │ ├── nuclear_test.go\\n│ │ │ │ │ │ ├── sdpay.go\\n│ │ │ │ │ │ ├── sdpay_test.go\\n│ │ │ │ │ │ ├── sesame.go\\n│ │ │ │ │ │ ├── shanfu.go\\n│ │ │ │ │ │ ├── shengtian.go\\n│ │ │ │ │ │ ├── shengtian_test.go\\n│ │ │ │ │ │ ├── up.go\\n│ │ │ │ │ │ ├── up_test.go\\n│ │ │ │ │ │ ├── wan_xin.go\\n│ │ │ │ │ │ ├── wan_xin_test.go\\n│ │ │ │ │ │ ├── wowspay.go\\n│ │ │ │ │ │ ├── wowspay_test.go\\n│ │ │ │ │ │ ├── wtr.go\\n│ │ │ │ │ │ └── wtr_test.go\\n│ │ │ │ │ ├── config.go\\n│ │ │ │ │ ├── errors.go\\n│ │ │ │ │ ├── event.go\\n│ │ │ │ │ ├── event_handlers.go\\n│ │ │ │ │ ├── events.go\\n│ │ │ │ │ ├── metrics.go\\n│ │ │ │ │ ├── models.go\\n│ │ │ │ │ ├── service.go\\n│ │ │ │ │ ├── service_test.go\\n│ │ │ │ │ ├── task.go\\n│ │ │ │ │ └── worker.go\\n│ │ │ │ ├── queue\\n│ │ │ │ │ ├── channel\\n│ │ │ │ │ │ ├── batch_six_handler.go\\n│ │ │ │ │ │ ├── channel.go\\n│ │ │ │ │ │ ├── init.go\\n│ │ │ │ │ │ └── yuhv_handler.go\\n│ │ │ │ │ ├── channel_session_test.go\\n│ │ │ │ │ ├── channel_task_handlers.go\\n│ │ │ │ │ ├── handlers.go\\n│ │ │ │ │ ├── init.go\\n│ │ │ │ │ ├── manager.go\\n│ │ │ │ │ ├── queue.go\\n│ │ │ │ │ ├── service.go\\n│ │ │ │ │ └── session.go\\n│ │ │ │ ├── aibo.go\\n│ │ │ │ ├── aibo_test.go\\n│ │ │ │ ├── apple.go\\n│ │ │ │ ├── apple_shark.go\\n│ │ │ │ ├── apple_shark_test.go\\n│ │ │ │ ├── batch_six.go\\n│ │ │ │ ├── batch_six_test.go\\n│ │ │ │ ├── c_trip_self.go\\n│ │ │ │ ├── card_type.go\\n│ │ │ │ ├── card_type_test.go\\n│ │ │ │ ├── careless.go\\n│ │ │ │ ├── careless_test.go\\n│ │ │ │ ├── daili.go\\n│ │ │ │ ├── eggplant.go\\n│ │ │ │ ├── eggplant_test.go\\n│ │ │ │ ├── fat_six.go\\n│ │ │ │ ├── fat_six_test.go\\n│ │ │ │ ├── favorable_clouds.go\\n│ │ │ │ ├── favorable_clouds_test.go\\n│ │ │ │ ├── flyfish.go\\n│ │ │ │ ├── flyfishv2.go\\n│ │ │ │ ├── heepay.go\\n│ │ │ │ ├── heepay_test.go\\n│ │ │ │ ├── init.go\\n│ │ │ │ ├── init_test.go\\n│ │ │ │ ├── jd.go\\n│ │ │ │ ├── jinke.go\\n│ │ │ │ ├── jx.go\\n│ │ │ │ ├── jx_test.go\\n│ │ │ │ ├── kuaifu.go\\n│ │ │ │ ├── luban.go\\n│ │ │ │ ├── luban_test.go\\n│ │ │ │ ├── magic_fish.go\\n│ │ │ │ ├── mf178_v2.go\\n│ │ │ │ ├── mf178_v2_test.go\\n│ │ │ │ ├── middle-open.go\\n│ │ │ │ ├── middle-open_test.go\\n│ │ │ │ ├── myself.go\\n│ │ │ │ ├── ninja.go\\n│ │ │ │ ├── ninja_test.go\\n│ │ │ │ ├── nuclear.go\\n│ │ │ │ ├── php.go\\n│ │ │ │ ├── pool.go\\n│ │ │ │ ├── qixi.go\\n│ │ │ │ ├── qixi_test.go\\n│ │ │ │ ├── scream.go\\n│ │ │ │ ├── scream_test.go\\n│ │ │ │ ├── sdpay.go\\n│ │ │ │ ├── self.go\\n│ │ │ │ ├── sesame.go\\n│ │ │ │ ├── shanfu.go\\n│ │ │ │ ├── shanfu_test.go\\n│ │ │ │ ├── shengtian.go\\n│ │ │ │ ├── star_silence.go\\n│ │ │ │ ├── star_silence_test.go\\n│ │ │ │ ├── t_mall_game.go\\n│ │ │ │ ├── trade_cat.go\\n│ │ │ │ ├── trade_cat_test.go\\n│ │ │ │ ├── up.go\\n│ │ │ │ ├── walmart.go\\n│ │ │ │ ├── walmart_self.go\\n│ │ │ │ ├── walmart_test.go\\n│ │ │ │ ├── wanxin.go\\n│ │ │ │ ├── wowspay.go\\n│ │ │ │ ├── wowspay_test.go\\n│ │ │ │ ├── wtr.go\\n│ │ │ │ ├── yuhv.go\\n│ │ │ │ └── yuhv_test.go\\n│ │ │ ├── models.go\\n│ │ │ └── supplier_interface.go\\n│ │ ├── base_service.go\\n│ │ ├── base_service_test.go\\n│ │ ├── merchant_hidden_config.go\\n│ │ ├── merchant_hidden_config_test.go\\n│ │ ├── pay_service.go\\n│ │ ├── pay_solve.go\\n│ │ ├── pay_solve_test.go\\n│ │ └── settle_service.go\\n│ ├── swagger\\n│ │ ├── swagger.json\\n│ │ └── swagger.yml\\n│ ├── tasks\\n│ │ ├── order.go\\n│ │ └── order_test.go\\n│ └── utils\\n│ ├── fingerprint\\n│ │ ├── audio.go\\n│ │ ├── canvas.go\\n│ │ ├── doc.go\\n│ │ ├── fingerprint.go\\n│ │ ├── fingerprint_test.go\\n│ │ ├── fonts.go\\n│ │ ├── screen.go\\n│ │ ├── timezone.go\\n│ │ └── webgl.go\\n│ ├── useragent\\n│ │ └── useragent.go\\n│ ├── AES_ECB.go\\n│ ├── bank.go\\n│ ├── date_time.go\\n│ ├── dm_proxy_strategy.go\\n│ ├── encryption.go\\n│ ├── md5.go\\n│ ├── proxy_pool.go\\n│ ├── proxy_pool_test.go\\n│ ├── random.go\\n│ ├── sign_verify.go\\n│ ├── sign_verify_test.go\\n│ ├── sort_go.go\\n│ └── wait.go\\n├── CLAUDE.md\\n├── build.sh\\n└── main.go\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"4a2f350946b54dea0716d3cbeb98f648050d113b","last_commit_update":"2025-10-07T23:59:59+08:00","gmt_create":"2025-08-22T10:50:23.389442+08:00","gmt_modified":"2025-10-08T20:18:48.9188246+08:00","extend_info":"{\"language\":\"zh\",\"active\":true,\"branch\":\"production\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"\"}"}} \ No newline at end of file +{ + "knowledge_relations": [ + { + "id": 243, + "source_id": "89d888b3-2b22-4be7-8c3e-66e1f9cef86c", + "target_id": "0fb51e95-8a1d-45fe-96b2-632c00da5541", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 0fb51e95-8a1d-45fe-96b2-632c00da5541", + "gmt_create": "2025-10-08T20:18:48.663272+08:00", + "gmt_modified": "2025-10-08T20:18:48.663272+08:00" + }, + { + "id": 244, + "source_id": "89d888b3-2b22-4be7-8c3e-66e1f9cef86c", + "target_id": "75b363d5-4074-4921-9ada-579b8f5a30c4", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 75b363d5-4074-4921-9ada-579b8f5a30c4", + "gmt_create": "2025-10-08T20:18:48.6729736+08:00", + "gmt_modified": "2025-10-08T20:18:48.6729736+08:00" + }, + { + "id": 245, + "source_id": "89d888b3-2b22-4be7-8c3e-66e1f9cef86c", + "target_id": "5c05b03a-d7c9-43f5-94c6-1f4ea2793f19", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 5c05b03a-d7c9-43f5-94c6-1f4ea2793f19", + "gmt_create": "2025-10-08T20:18:48.6804484+08:00", + "gmt_modified": "2025-10-08T20:18:48.6804484+08:00" + }, + { + "id": 246, + "source_id": "89d888b3-2b22-4be7-8c3e-66e1f9cef86c", + "target_id": "70b6c90d-240f-4eb3-abc6-50fb7add6fc3", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 89d888b3-2b22-4be7-8c3e-66e1f9cef86c -\u003e 70b6c90d-240f-4eb3-abc6-50fb7add6fc3", + "gmt_create": "2025-10-08T20:18:48.6888578+08:00", + "gmt_modified": "2025-10-08T20:18:48.6888578+08:00" + }, + { + "id": 247, + "source_id": "013b2790-e5e2-4879-8a97-c5dee7adde89", + "target_id": "13bd83fa-402e-438b-a012-6d53eac7c39d", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e 13bd83fa-402e-438b-a012-6d53eac7c39d", + "gmt_create": "2025-10-08T20:18:48.696662+08:00", + "gmt_modified": "2025-10-08T20:18:48.696662+08:00" + }, + { + "id": 248, + "source_id": "013b2790-e5e2-4879-8a97-c5dee7adde89", + "target_id": "d0e098cc-486d-48ae-99b6-dae8bd81b609", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e d0e098cc-486d-48ae-99b6-dae8bd81b609", + "gmt_create": "2025-10-08T20:18:48.7049818+08:00", + "gmt_modified": "2025-10-08T20:18:48.7049818+08:00" + }, + { + "id": 249, + "source_id": "013b2790-e5e2-4879-8a97-c5dee7adde89", + "target_id": "8a821f9b-5ad9-4602-96c2-724299a01a8b", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e 8a821f9b-5ad9-4602-96c2-724299a01a8b", + "gmt_create": "2025-10-08T20:18:48.7129288+08:00", + "gmt_modified": "2025-10-08T20:18:48.7129288+08:00" + }, + { + "id": 250, + "source_id": "013b2790-e5e2-4879-8a97-c5dee7adde89", + "target_id": "3077240f-f00b-4f59-a8ce-8991408c4b96", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 013b2790-e5e2-4879-8a97-c5dee7adde89 -\u003e 3077240f-f00b-4f59-a8ce-8991408c4b96", + "gmt_create": "2025-10-08T20:18:48.7266219+08:00", + "gmt_modified": "2025-10-08T20:18:48.7266219+08:00" + }, + { + "id": 251, + "source_id": "7424e713-8de3-415b-ab24-f02a1102bdbc", + "target_id": "026c8458-a7b5-44cf-b052-10b1cd6604f2", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 7424e713-8de3-415b-ab24-f02a1102bdbc -\u003e 026c8458-a7b5-44cf-b052-10b1cd6604f2", + "gmt_create": "2025-10-08T20:18:48.7389167+08:00", + "gmt_modified": "2025-10-08T20:18:48.7389167+08:00" + }, + { + "id": 252, + "source_id": "7424e713-8de3-415b-ab24-f02a1102bdbc", + "target_id": "16f1ef56-d692-41dd-84d7-c41790f98abb", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 7424e713-8de3-415b-ab24-f02a1102bdbc -\u003e 16f1ef56-d692-41dd-84d7-c41790f98abb", + "gmt_create": "2025-10-08T20:18:48.7470347+08:00", + "gmt_modified": "2025-10-08T20:18:48.7470347+08:00" + }, + { + "id": 253, + "source_id": "7424e713-8de3-415b-ab24-f02a1102bdbc", + "target_id": "f0a4a14b-8948-4372-a8b7-6974e4286083", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 7424e713-8de3-415b-ab24-f02a1102bdbc -\u003e f0a4a14b-8948-4372-a8b7-6974e4286083", + "gmt_create": "2025-10-08T20:18:48.7544795+08:00", + "gmt_modified": "2025-10-08T20:18:48.7544795+08:00" + }, + { + "id": 254, + "source_id": "6e2e98a9-36f3-46c1-b2f2-db52c4526f11", + "target_id": "302aea38-1949-48e6-bd95-96cb17b84d12", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 6e2e98a9-36f3-46c1-b2f2-db52c4526f11 -\u003e 302aea38-1949-48e6-bd95-96cb17b84d12", + "gmt_create": "2025-10-08T20:18:48.7748735+08:00", + "gmt_modified": "2025-10-08T20:18:48.7748735+08:00" + }, + { + "id": 255, + "source_id": "6e2e98a9-36f3-46c1-b2f2-db52c4526f11", + "target_id": "b527099a-0510-438d-a4ec-b8ed8642ae8e", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 6e2e98a9-36f3-46c1-b2f2-db52c4526f11 -\u003e b527099a-0510-438d-a4ec-b8ed8642ae8e", + "gmt_create": "2025-10-08T20:18:48.782745+08:00", + "gmt_modified": "2025-10-08T20:18:48.782745+08:00" + }, + { + "id": 256, + "source_id": "6e2e98a9-36f3-46c1-b2f2-db52c4526f11", + "target_id": "f5af27a6-1bd2-4346-a7a8-2682705f09c5", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 6e2e98a9-36f3-46c1-b2f2-db52c4526f11 -\u003e f5af27a6-1bd2-4346-a7a8-2682705f09c5", + "gmt_create": "2025-10-08T20:18:48.7906626+08:00", + "gmt_modified": "2025-10-08T20:18:48.7906626+08:00" + }, + { + "id": 257, + "source_id": "d2d80765-26c3-4c0b-a302-612693077838", + "target_id": "3f30d007-e6cc-4636-8ab7-f10562baff6a", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: d2d80765-26c3-4c0b-a302-612693077838 -\u003e 3f30d007-e6cc-4636-8ab7-f10562baff6a", + "gmt_create": "2025-10-08T20:18:48.7985877+08:00", + "gmt_modified": "2025-10-08T20:18:48.7985877+08:00" + }, + { + "id": 258, + "source_id": "d2d80765-26c3-4c0b-a302-612693077838", + "target_id": "3b453233-b2ab-4942-9a6c-d92a5a3897c0", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: d2d80765-26c3-4c0b-a302-612693077838 -\u003e 3b453233-b2ab-4942-9a6c-d92a5a3897c0", + "gmt_create": "2025-10-08T20:18:48.8065544+08:00", + "gmt_modified": "2025-10-08T20:18:48.8065544+08:00" + }, + { + "id": 259, + "source_id": "d2d80765-26c3-4c0b-a302-612693077838", + "target_id": "93cae8db-9a04-407a-8446-250cdc33f661", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: d2d80765-26c3-4c0b-a302-612693077838 -\u003e 93cae8db-9a04-407a-8446-250cdc33f661", + "gmt_create": "2025-10-08T20:18:48.8147799+08:00", + "gmt_modified": "2025-10-08T20:18:48.8147799+08:00" + }, + { + "id": 260, + "source_id": "d0e098cc-486d-48ae-99b6-dae8bd81b609", + "target_id": "b5f75438-5c24-4f0f-be95-f857806fcfaf", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e b5f75438-5c24-4f0f-be95-f857806fcfaf", + "gmt_create": "2025-10-08T20:18:48.8253615+08:00", + "gmt_modified": "2025-10-08T20:18:48.8253615+08:00" + }, + { + "id": 261, + "source_id": "d0e098cc-486d-48ae-99b6-dae8bd81b609", + "target_id": "4a9995be-1002-4a48-bf07-8b4f725756d0", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e 4a9995be-1002-4a48-bf07-8b4f725756d0", + "gmt_create": "2025-10-08T20:18:48.8339278+08:00", + "gmt_modified": "2025-10-08T20:18:48.8339278+08:00" + }, + { + "id": 262, + "source_id": "d0e098cc-486d-48ae-99b6-dae8bd81b609", + "target_id": "b2cf330f-309b-4fa5-980c-c5809a143195", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e b2cf330f-309b-4fa5-980c-c5809a143195", + "gmt_create": "2025-10-08T20:18:48.8418303+08:00", + "gmt_modified": "2025-10-08T20:18:48.8418303+08:00" + }, + { + "id": 263, + "source_id": "d0e098cc-486d-48ae-99b6-dae8bd81b609", + "target_id": "047d142f-ec46-4f80-83d3-c377a86858b8", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: d0e098cc-486d-48ae-99b6-dae8bd81b609 -\u003e 047d142f-ec46-4f80-83d3-c377a86858b8", + "gmt_create": "2025-10-08T20:18:48.8549301+08:00", + "gmt_modified": "2025-10-08T20:18:48.8549301+08:00" + }, + { + "id": 264, + "source_id": "8a821f9b-5ad9-4602-96c2-724299a01a8b", + "target_id": "9c7904f8-0b4a-422b-806d-55c96bec2fe6", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 8a821f9b-5ad9-4602-96c2-724299a01a8b -\u003e 9c7904f8-0b4a-422b-806d-55c96bec2fe6", + "gmt_create": "2025-10-08T20:18:48.8672021+08:00", + "gmt_modified": "2025-10-08T20:18:48.8672021+08:00" + }, + { + "id": 265, + "source_id": "8a821f9b-5ad9-4602-96c2-724299a01a8b", + "target_id": "2500aa21-fe32-4057-a5ad-11fbd4d19546", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: 8a821f9b-5ad9-4602-96c2-724299a01a8b -\u003e 2500aa21-fe32-4057-a5ad-11fbd4d19546", + "gmt_create": "2025-10-08T20:18:48.874549+08:00", + "gmt_modified": "2025-10-08T20:18:48.874549+08:00" + }, + { + "id": 266, + "source_id": "b5f75438-5c24-4f0f-be95-f857806fcfaf", + "target_id": "e50eff25-5123-4c73-8a3b-487293043f2f", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e e50eff25-5123-4c73-8a3b-487293043f2f", + "gmt_create": "2025-10-08T20:18:48.8845346+08:00", + "gmt_modified": "2025-10-08T20:18:48.8845346+08:00" + }, + { + "id": 267, + "source_id": "b5f75438-5c24-4f0f-be95-f857806fcfaf", + "target_id": "ed7bbb93-3e0c-49fe-b1dd-a92d8176638e", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e ed7bbb93-3e0c-49fe-b1dd-a92d8176638e", + "gmt_create": "2025-10-08T20:18:48.8929564+08:00", + "gmt_modified": "2025-10-08T20:18:48.8929564+08:00" + }, + { + "id": 268, + "source_id": "b5f75438-5c24-4f0f-be95-f857806fcfaf", + "target_id": "243ba92b-7b56-4596-9c54-31905f65e471", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e 243ba92b-7b56-4596-9c54-31905f65e471", + "gmt_create": "2025-10-08T20:18:48.9007605+08:00", + "gmt_modified": "2025-10-08T20:18:48.9007605+08:00" + }, + { + "id": 269, + "source_id": "b5f75438-5c24-4f0f-be95-f857806fcfaf", + "target_id": "99e9dc6d-e943-4712-a961-7a053872ad8f", + "source_type": "WIKI_ITEM", + "target_type": "WIKI_ITEM", + "relationship_type": "PARENT_CHILD", + "extra": "Wiki parent-child relationship: b5f75438-5c24-4f0f-be95-f857806fcfaf -\u003e 99e9dc6d-e943-4712-a961-7a053872ad8f", + "gmt_create": "2025-10-08T20:18:48.9088886+08:00", + "gmt_modified": "2025-10-08T20:18:48.9088886+08:00" + } + ], + "wiki_catalogs": [ + { + "id": "3f5378b4-a8c2-4361-90a2-caf79aeba7fb", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "项目概述", + "description": "project-overview", + "prompt": "创建关于kami_gateway项目的全面概述内容。解释该项目作为一个基于Go语言和Beego框架的高性能支付网关系统的核心目的和架构设计。详细描述其主要功能,包括多渠道支付处理、订单调度、代付请求和回调通知等。阐述系统整体架构,包括MVC模式的应用、各核心组件(控制器、服务层、模型层)之间的关系,以及启动流程(从main.go开始的初始化过程)。结合CLAUDE.md中的信息,说明项目的技术栈(Beego、OpenTelemetry、Redis、MySQL、RabbitMQ)及其在系统中的作用。为初学者提供概念性介绍,同时为高级开发者提供技术细节,如分布式追踪的集成和异步任务队列的工作机制。包含一个简单的系统架构图描述,并举例说明一个支付请求从进入系统到完成的完整数据流。", + "progress_status": "completed", + "dependent_files": "main.go,CLAUDE.md", + "gmt_create": "2025-10-08T20:04:49.3551015+08:00", + "gmt_modified": "2025-10-08T20:07:08.687419+08:00", + "raw_data": "WikiEncrypted:0MI1/XkBoMl0lTbK6t0Cn/+8FdvqrJ62ianMLvZj02elJtBUgH0Ns0veIx1WPtM9wwkxI+/XAqHLxJLlHB8wV5ZPaqnpZD68qW6viSXvNxPJNDAD05FZhFLjO5QfwnFHWPmp8131gwmlV3+yUNfSuYNEWqrJ75L2XuQDuIDW0SOK99teLJoUi45zev+K43mRPdrh41HdJlZE/Jsz6+HE0EYNTTPdgFIWhJ2lfkhN6ub5MQ+yfytKxGTF0NG8E1tg+dZ1HeVX97YzoSV8ppoxUrbe2ZImsGFEojjXbvHGVyOOoqY4gCdFXLjVAAIKXNvwpbtoOdhlIwUgZqhdd3M2mUYoz1vTUEqzi5f2Tzht3uo7ndi3oVtIQjt7kNlcreks6wxImWgkbUgJY8S27IpbKbVdtRRMM9vWs1V6QxUSNZvAKnAr0qaCRbL5Mq5WP35NS3BK2wQhnRIrGRjBuOioB0kP6Ms31o8bl+vzVam9+QDLWSftKBX6XBWRzLf124p0BmkF9qZ7wReMn4fNvtVC6yoJM8TktA6XT9MsHi8eBrEaR7oF3LIG3nlIWKRWHJNQod+O3OglG5SJzuAu7MeFDq6fxHGnQXVJ8IDakA02Gf207gtl5UwjMoj15rlSeOqDEUSE7q/1BGZ7NceAs2/nhGH+Y4Sj0jXa19bFNspgcbc2mmSChYjkFdTkJ8f1N2RqsdywRfnAxsePQz34Cv4RcWawgK1rFf73QxegrlXZ+Bz/M+Ojzdsow5hox/ezQYbw5+LmStYx8+bu4uoUk8u3SVYql5x7z2//bYBaV/WmkQlxzYSHEx3pN9qMb9cdod6e599OeMLRY5XKRGBCaXEhdGO/Hd1dvC+1ghnNlHtAM+euctI+Xe4jNA+KjwkI58OBc9KrCag1IU1geZCkAyM6U4HiSMNVRhC9uiKWNhprOXPj6jtO5Dui0MhP/L8R33l2sR8Cp2L+pQrVyFV+GtFSfVvWC1eyc/qqK34F1P5BrulAgFDf8Kwc37rMwrMymK5tseELGRyKdNLaU1UvALyhXJINsExpwGedpUI3d6eN0qNCRdE3/NYy0t1S2BHKJM4w3QBcUsyUxdtWQA5EYoxn11U43hp348DWyiMgqyndua71AsT5XKKthljr2gmPSqRpGQ7c/pfzprYVPHDP9HL8Scqv7nmOWmWzR5kEsn9mPo9M3RJAHsYUw27U6e9LeKycWi2A3Bij7VKdyDHFh9/DV/3JJ0EPvj3RH8bzDpYrVzUO33qcnJE5Vt9ek+TPXUZnowOH9u4b9KLO9jj6oyBNf4km/UrHVC6X0DcoBkg+9ks9EuQ0URuKlPQO/uZR6kRhgocoyYicmu2IhKruaibS4lLTomlAtrNPScOrHfQMMzE59GFtT5hz0FRB3r7NxdAyTWpiZLM0HRhBHiLCbHnRR3HYyr3kgdnFaystz+1lm47pTzoFzSq6mDNYqP/CW7BX" + }, + { + "id": "ff8a9c9d-2dc0-433a-a1d4-b84ee2141635", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "订单模型", + "description": "order-model", + "prompt": "创建全面的订单模型文档,聚焦于order_info.go中的OrderInfo结构体。详细解释每个字段的含义、数据类型及其业务作用,特别是订单状态(Status)、支付金额(FactAmount)、通道标识(RoadUid)等关键字段。描述订单状态的完整生命周期,包括从创建、支付、成功/失败到退款、冻结/解冻的状态流转逻辑。阐明OrderInfo与order_profit_info、order_settle_info、platform_profit等关联模型的关系,说明其一对多或一对一的数据关联。提供ER图描述这些实体之间的关系。文档需包含通过Beego ORM进行订单创建、查询、更新的代码示例,并讨论高频查询字段(如MerchantOrderId、BankOrderId、Status)的索引优化策略。同时,解释订单数据的归档与清理机制,以及在高并发场景下的数据一致性保障措施。", + "parent_id": "a5d56738-c20f-4178-9f81-d01bb592f194", + "progress_status": "completed", + "dependent_files": "internal/models/order/order_info.go,internal/models/order/order_profit_info.go,internal/models/order/order_settle_info.go,internal/models/order/platform_profit.go", + "gmt_create": "2025-10-08T20:05:09.8999413+08:00", + "gmt_modified": "2025-10-08T20:10:13.3178855+08:00", + "raw_data": "WikiEncrypted:1TcXmWRnDAgI41cGfWTUk0mu632uXt6rCt+zlwbNXH3cI5ea0ul/gH1ctKZ1sOQGRugrR4SG9AWauLAeU1/9zDoT7NsiqMF9p74EyuzRsReCaZHq0ftesSjQISh1ms08c9zO/AxEYtaFLlQDfeRz7BKMoCC+i4dQSOjRgcas1dh1raG6BTLXjiJdoWoVDHbMqLf3WbcD+j8J5ngFzB87vyiPK9nC3cYI8ziVPFI1kjy7zs1Ju1D7zi5yjg1hyylSm+iumS45vif3MZSoeL7KOwj4JvhfOpDkNngKQDlDJ2r8gGQd32M/P9rDj2oFaOsLr74QWf/ShgrhFg9CEjk9H9safU0BFoVzk33kJXE4/eFrbQTYG1Ytw2Wyu2QVMDo5GsYyU1e7Rb75SRe9/S45LEsWMawreZmtUSkKOc2F2px+IgXba9xv4O/3p3JmPQ8Qu6Z4Xm7kx7W8u4M0qzxV6sNOK4C2jHqPEO05J6JbCkeS3GJlNd+bm3TGPCnOD5aV6EBQUkMhtZT2xMlHloKDRhV8ENaxqT4pd51o5wx9j6Q0Af/BslcRBQdX2F9GNsQ8XsarzaP+erN/pgjyeL5VIaaTKzqS0JNq1DDVlm4++LHtyfP+WaYcJGdtLiahwDmLh/oCy560iMUG+RZJLI2eCvcnH/PwvaUB43NJG9djkqYu+AzbDHlRHwXhdjmeOoiMKnb/MVfg1p2uj4BCigi6efzj4L2ziO7kH8bb379jlGZ1Eo5KVIbb4Kou1YZyqDbG4mz4LCAibtUHQy3Jtvw4FtfsvHAEF50kXj9yLEGCG4bLbgWnHOdYndyTEhSdGLU6dbtA+10UTB8Q/4tppVfEapBdDIg1qW0N1LFpq+Bnd1I3HlMqfUivuvHJmA38JpDDbkbjQLk+puMZevIeYzJirTNUDgJFLQy5NkdV1biKHw7SqSRJ6k9wQ0w6aQdDrPGiCEv35Wtk6LJTM1jvupmYoU1/RSP6Qb7BglHLH9BLlTsDO6eenXGr47ZaNFA/d7iiKTOayr0HZyAZu4ur9hRyqn1Itwc11aQvinP8LmEk3OPDxe/wi+lbw8Nm2UnNed0C+cly6YNcj1ArdlY3QsJ2rkzjxPd5ioOd7+sQyC+cQX3IJmFQM9VfSs8kPYDpiA8ykakv6xh0TsL47JoWP86WkDUQDuqQ2uLchVVAYFrWC554N8+CKUUXTLsBYmNnRLnP9SgD7AO/3NT+AnH6pXcQy/hnRZN4Q9osisJXeFYr8vx7NY/zwW5zQzZnh54HZ45XXpGJuNXcHelh5b1As/jgbqxWYuK+z9JcII3ppT39XzWfh04B27SOUjdeCyFyLavZJEojzZMQizfhEGx5PX2TrAWhdBI5/8Khc3PQv74nfaIATRT2FbHhPcerDrLokEmCiNbzTo72lD25WkddyQdWf3qSk3tYfjUB254tT4vZFMjGqWUpOyiDqRYl8BP0RplC5tLr1/+KbGahSAh4KE+d9IcafB0rPgABHUriXD8hQ4bLVcW+3YMmclGOGDKJTNJjTuKm31U/vGYZaExnq0IwtOEx+sHn5hgLD31Q/3p4JtmTuGwg4FEs7lIQaBnMiYJDspcQpP9xjwQh+5FSsq1Lv3ze2gB0fVWBRuC9i3n+2BWvgFBFSVgA9b+blfIAMzGxldcwxRfl73S6DcQdAYDsJkqzGTYoU8bAPFa7HYqTG4fUt7PZZKQavrWJkCLwENFF", + "layer_level": 1 + }, + { + "id": "a21144d5-112d-4642-a874-64fb8a1ea84f", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "Beego 框架集成", + "description": "beego-framework", + "prompt": "创建关于 Beego v2 框架在 kami_gateway 项目中集成与应用的详细文档。重点说明 Web 服务的启动流程(web.Run())、路由注册机制(router.go 中的命名空间与控制器绑定)、控制器继承结构(base_controller.go 的封装)以及中间件集成方式。结合代码实例,展示 RESTful API 接口如何通过 Beego 的注解路由映射到具体控制器方法。解释 Beego ORM 的自动模型注册机制(models/init.go)及其与 MySQL 数据库的交互模式。提供性能调优建议、常见陷阱规避策略,并说明框架升级兼容性注意事项。", + "parent_id": "576b2803-bcc0-4769-89b3-54c89e6b7381", + "progress_status": "completed", + "dependent_files": "main.go,internal/routers/router.go,internal/controllers/scan_controller.go,internal/controllers/order_controller.go", + "gmt_create": "2025-10-08T20:05:11.0590792+08:00", + "gmt_modified": "2025-10-08T20:11:20.9567628+08:00", + "raw_data": "WikiEncrypted:pYbZ5lRfULAG9jugU9XK63rJ8GPtKRTSEbtQAg5JLYWXJILzfHFhMg9BW6Hr9mzVoxQ045fHqDzCfMmueW2jL2W6NCEsvVpIHvX+6rH8HRYhUWh+pAll0hDV9OGuBX6B//sGA4Scx6WgPH7v6Pxji5huDlnPxiJ8XTKuYY/UX3HWMBdp+MHikW0btSfjxfOHXjTCT8QXqvwq95Yk90EH4ZsTtPqgi4YTt14YldgRFsqWKE1ZwNy5gcgkTxyVxKjxYKByJh9ppwO42retGbh3OxRKXjznM18i6EtUzq9kq7WPT62pjG49LYk8JDgR1uvpwkMocJ5+RSFSCa3rp9ww2GwDE6Zn7JP4kkXsMs/PjMN9NJNL4rgk3IRY3mvfMs7bETa+t9TMW2G9n3fn/0SR+9+xkiY88Uw3XsFFkqoMunWEiQjs9o4OQJQjlm9E3pQQO5tQJ+rBA5uK/d3Za5rTXYWYRZ9YxSoJG7Ljixn2OSrq9QB5Bymy5xjduCS+m1ONtDpsKumS9CUes5iCicOQx7J4lox6/a9dl/r5TcnIeEjtQEGTrjy8hzovQLoAeTTbHspfdqBPG3O3bkWP2Josr0F9nbV/9HLPYWJURk+GNT7a/ikul0weorlQyFnkoVLSoNKN1O4ROlxEywcd5bBLMWSDmnnjfnnV8hsQnGfdXnFpyy7AsxYpHMwYsqRCetnTY62QT5ytW14k89q2rpkcgVRNta4K/woMb+vQLCv1dC78gsq7iX/XeQ79wABLTsi0FkyF5BWAAXVX81dxj64mN5C/EXp3wMMZtHnHy+zbytSuN9chXtGdQl9XZYMeF0v/nsZUtxepBkgitrzfKfSYbTZLjJAlUKTQk5kPJmWSrZx83nwTRTCx42ecYCMOwqsSsGPi1YlsLTmFBJCpRnlrUuNFewRrPEfOIOyqGVeM4MG452v5nFeDoYpeJySc5XPryqgJR4L80OF9aSK6pXww8NhbR42HBhtUWicMiDy6+oCH/ZCbW8mWWpwnOi3miFcg3cfcQJ1EnRR/P0wba6K15KMO7exmNCe6cwfqTlptyM49qo2O/bwpQYZ7o9p6abSXXtF7Pfa8K3gnMd2GOyd7cI6DYEw0noI0tu6FtxKk6WY6Sg4jy0Xm0xVBXLSzqNZwiPlSAhONcEsvoessVgpOyYBCL3NFDfBlL+wAeeV7taw5WtfYCzpYwr1Uojja41QZTZlH6lLQa18n9JaH4wfKbnM1dzpY3TXkR+Pskax3PvkNaK2Kc8XJ09sI3eEZCeqa", + "layer_level": 1 + }, + { + "id": "0fd4a109-43f9-4cea-9416-4cd2bcafd325", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "支付API", + "description": "payment-api", + "prompt": "为kami_gateway的支付相关API创建详细文档,重点覆盖/gateway/scan和/gateway/createOrder端点。解释这些API如何处理支付下单请求,包括请求参数(如orderNo、productCode、orderPrice、notifyUrl等)和签名验证机制(使用sign_verify.go中的MD5签名)。详细说明请求流程:从接收商户请求、参数验证、选择支付通道(ChooseRoadV2)、生成订单记录到调用第三方支付渠道(通过third_party.GetPaySupplierByCode)。提供完整的JSON请求/响应示例,解释ScanSuccessData和ScanFailData响应结构。文档应包含错误处理机制,如订单重复提交限制和IP限制。同时说明CreateOrder接口如何生成支付链接(payUrl)并支持自有渠道与第三方渠道的区别处理。", + "parent_id": "80fb1e42-5bd2-4870-8b88-77d31ff5c478", + "progress_status": "completed", + "dependent_files": "internal/controllers/scan_controller.go,internal/routers/router.go,internal/schema/request/order.go,internal/schema/response/pay_resp.go", + "gmt_create": "2025-10-08T20:05:17.6527387+08:00", + "gmt_modified": "2025-10-08T20:10:53.955797+08:00", + "raw_data": "WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JomSPSNlxixXQGITg+XBkQR1A651zRsXgTTzt7TTgrAOtmF6FZNGeCDV26qfOUdn+qVk5cL/IbKTPA9hIm7a/xk6pmHM6fw+bPPtDrw4oj2+zna4fs1ZFDyzNcZmQYGMwKCUXXliSL9bOvtCvSOcIJz7ACiI6Z381v4NL/F/u0/8GhMzWxqWonV4+P5FbRu+P9yH+TYARkHktb+lupqn9J/ezWrIBzOwmREpiphWwdTMs1pLjCYZOaIkazh/lSzn0K2ck1pkFCGSibZ1j7CXgiREdG6aWZ6AenuDccdYk0IfrzC1npbgli5ePCFXtVgIELr5K5d6IpDIa7z6MrG36oJG9NFgWpklgbA4uEWmvaxYJiJEVsgDwiZnM0gRRcvcPZoz2aDyRB/wzQvWeamL1Vx0J3wtIhwwuhqnN2GIeK8ekDMYjuYNVlZPX1RylDPH26MwB4BGtS/exe1mPY9FKcY6oVAi8HjPGY9+6W+npRBonWY7/Ye4QPlUc4nKx8YhN/u/aqn9yWe7qZtebAZDRmdUAxpRyCCN/xrpY0tYnMMHvX4GsR+y4duyKOiwNWbRYL8qhljUuOpo6EAANOL/tvu+KGA1gfE5GISxWQv1rBXQQtOLmiEXO1LSftIHvB9KdtJe8LBviMBhoIdCCuh58qWzSUcYCN0SgeNh9BjPuaTPLyW4wDyFcYR6STFQurOb+rgNYlu1/KMw9ufhUCR2StQTbWJW8WUuieoilsng3NsdiBxjZuzOKr+oplUs+bum1SYUZujRmrg5qDahaNSBicDhEa/jCsYELjMdDjIzZZ8y9gf+PmI/Z3A3lavT3vNtKD+kiPyOFocO3K9gp8T/PW44aoUDlyVRzfNExpc9qsCIOmAh2qx2fSnLp/Ormt0+kw1AHJEauHFcCsB4AOgcpe5vcLsd//vfNytudMaqu6nHQ8+icoUFH96PIl40PVFy7oOucQ7qj8BADWeMgWRfY3lbpXRMUhBLHufRGbfWTrj/9nLdQZXK9cxysYzmOoC2n+0t+k5Q+jLg820QKVNAoYvuk7ywkv0cJWOFXsc6jUIVYmL1PxE488GjcGkn5x+8mHUyb295l8YSGTUPTllMYyV6cp5L3+/648S2vw0c5R/xe1w0sYygJZ1jNKTmALxdoXFJMmxzGq7nstG2+5/4KuvwTpPm5EdXxWeLBGlfEK0yKr6SIS8ecx+97L1Zjo4FWZ3/SLpMrypCw3P+XxPpnwIjLMIWquhmJvWox8oNe35Cvg+fqJdNccOkxc+VKWgI5tkAoj3+y5QH2CVwZW9is384QQmzJLS5ewW5bZCQv1KOhtg2hHwaddn89v/QvrXmJ7WsDEfiUIGkVZT4QhCDXxlHsvJ/z/egTtw1g7Wwy9Ct0Tyb5GKfa1TkIo7OSeYQMxS4mp9TsvK/OYh25paps8KyoirIQVQgAYaU6ZYBERw905swD40jGWG3duypzV3+bzpFuFe6+p4/u6LzwAh0Tw8=", + "layer_level": 1 + }, + { + "id": "3d1b720f-a641-456e-94d0-ff9db2b5568c", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "Docker部署指南", + "description": "docker-deployment", + "prompt": "创建详细的Docker部署指南。基于Dockerfile,解释多阶段构建过程:第一阶段使用golang:1.24镜像进行编译,设置GO111MODULE=on和GOPROXY=https://goproxy.cn,direct以加速依赖下载,并执行go mod tidy和go build命令生成静态二进制文件;第二阶段使用alpine:latest精简运行环境,安装必要的时区和证书支持,复制编译后的二进制文件和配置文件。详细说明docker-compose.yaml中的服务配置,包括构建上下文、容器名称、端口映射(127.0.0.1:22309:12309用于主服务,127.0.0.1:22390:12390用于监控)、卷挂载(配置和日志目录)以及外部网络1panel-network的连接。提供完整的本地部署步骤:从克隆代码库到执行docker-compose up -d启动服务。包含常见问题排查,如端口冲突、镜像构建失败、容器无法启动等解决方案。", + "parent_id": "53d903ba-6508-45b8-b48b-b3d00d3ed07a", + "progress_status": "completed", + "dependent_files": "deploy/Dockerfile,deploy/docker-compose.yaml", + "gmt_create": "2025-10-08T20:05:30.6660042+08:00", + "gmt_modified": "2025-10-08T20:10:46.0280433+08:00", + "raw_data": "WikiEncrypted:h7ADvj4WLJHyulzCl+z7kMT6DzaQnlgZj+Vph23KSPwCAKwAGu81Jfoj4zRMdPAHAjNjzOswrmpAVwnZuFSYbYxSzu7Ii0/Kr0LYNoxQ/RWaQfk9+ro807nPoRs7ljBxN7ilkXwnmbx4F634qhI1CNLRXg7hNq4tA44hr72/A9I2hiD+R06jsyntF3qKEJQeDfWk6IFhSFlV19C6drfngvf4mbHMITqtO11BKZrNBJjQ7s/F4N8OqUMf+q0JK3ZPj9NcHS6dvX1S/9BgQRCeucmzAVQ59NIGfYIfUB++eZc6bqOBvR/0bhsXbg1Z5UTM4lQYAZATSC0H+xqVUFeSHIqyH3PxBDGA734N6DA/qScKpfOzeMP1uBW32BJ3dTtvVYiu8iurr9brvKUBRTY7/jX8e4RFg6z77DvqmtwarcLKBis6VcDL91n7VanPj4W+4kKzvwC6IXbR7YXgm2hOkRmnr8QzGqLmxyymsYNo2wXPs5scHaj71HDpzGodfDLV9HZkrhNyR9FN7sTKq+EzWEUlbd5dRqYQAxWquA+/BNVwuGBsUR/77Cg6gJLIMQkIxb08umxCA5W0ClnQ+LgP/taVUBy2529V1JlptjIX50o8SnXJf7dC7K1sgN51928Ci9r4eJD3Wg3uOh/CjqlIYl0Tf+W9Sjw+saqf2VHveQBijnkQfiYDl9vCtjlPWzzHHSTAgPiQqtwxTihbmjDw0GBBwmjzKg4DuBtPlQn987VoTMO9ep0jNnzOFttOu0fRgBMmm7DPRQwcoLHUaJ7teS7xwjKeMpXaDGY5k5O3ZEDbso+KcquJT6e0dVsVo/EHWZv7/aVPvdccDZREIcTfn2Whl5s+O4p9gCqw8K6gjAIwM/UgYnANXL9q7vNwgJoXlkrvvcLouD2jcerdEOKPdJM2rlln3Qc0vIqJDzwK6xSM0j4Hp6Pr6hFrJDTvfP75xHudMxdWe8JlBkaFiOQgHWt4OYjPuGquFpxMkneb3NUMZbpOUW7NxMDXRIGu05tokBrWbjjU6LRQsInAhSv5Y9G6ZMY1gR8EJQrf2ZSgS7QALqg8QiQ1PF0ZP/Bog/yf3/aQpZv64U11sRSCvxhWczuOlNvCSoGgw+OLiD2Xm/1bbE0HOs0OcOoVLSg1iQnpqjyR1f+GHj+Mo5xNeBGJrYmBFLDYJk/4orLuM5t2nNuf96bUs8V+NmPLmN88cqhCgexE9UdkDNRwonMAKXS5CSG0BZH8+eHgHS+DOighe6kKTOEimBHL+Z/TPSCXXc7mdFx8QDNBIpXkmWMPWxJ2a2n6SLJsJv8QelsFjdLqeqXbsQBQ+RAe1FCPULP5VyRpLfE1KaiwPZvnK50HZzvihNwrs4atWiwAw9B0uNEZfbdCadv4o2oiBW/37zUkvOLFzCPyIBc+u7l4aBLYSpzkGhDLIPNCKvsdFtsTVTgsgPj7+PggYW/QFbgqtUB+EUqrve24rgCKRe0er2ZaqJTy4aXQbHfhOqoaf5dkQPAKE9qAPUSfkfpVO0ZzkJY+2ehN", + "layer_level": 1 + }, + { + "id": "7cc42a3a-553a-4702-9eaf-b76dd3628a17", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "支付服务架构", + "description": "payment-service-architecture", + "prompt": "创建支付服务架构的详细文档,聚焦于pay_service.go和pay_solve.go的实现机制。解释支付请求从控制器(scan_controller.go)进入系统后的完整处理流程,包括订单创建、状态管理、金额校验和结果回调等核心环节。深入分析支付解决方案(pay_solve.go)中的关键函数如SolvePaySuccessByAmountDifferent,说明其在处理实际支付金额与订单金额不一致时的业务逻辑。文档需涵盖服务层与模型层(order_info.go)的数据交互模式,展示如何通过上下文(context)传递分布式追踪信息。提供序列图说明从接收到扫码支付请求到最终更新订单状态的全流程,并讨论异常处理策略、重试机制和幂等性保障措施。", + "parent_id": "1ccdc69d-fc3b-4d08-9be6-169095e4a163", + "progress_status": "completed", + "dependent_files": "internal/service/pay_service.go,internal/service/pay_solve.go,internal/controllers/scan_controller.go,internal/models/order/order_info.go", + "gmt_create": "2025-10-08T20:05:33.9784679+08:00", + "gmt_modified": "2025-10-08T20:11:36.0497918+08:00", + "raw_data": "WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JvxO8KLLYdmkP5MiyHLrNi8YvD/ZlHRaEU+Ki/xv1XgB7U9taAOuEQEGNdrWJ4wheAmYaijjVKvdhNz58k/xaxuuqgmpOxt1if3RbdI2dvGdEAZ64D069hqGUue0BvhEJPSDLc74Uyt0t0yQFZNVE/dNgm4ZnN24YWN0mXHtGNGHCS/56OINC8R66Wk8e5tWvKmV/hef9n2CDeLrMDoBMjw4fw8eOQzsq42JwBaQOhdPY7f/73gdewEOeMQLO47psLUW26+elZ5HXh9RQZmDV/bLNvIJRarz4M3sY6UCP+4kGUCdLzOycPZavfQgpoJti7hsfRGFjJpLBMbL+ccsrxFPUpF4lMrN7d1l5HJgt2AYGd+48AUwqIw39l5VyCpwpSk2sU3wTNB2HMvzFFsJp2vorL98xgPnprBfj4rkCOZI478Pbbyh3XDf6nLpHqfJ7kMcf6c4/JF+AytcOWcVETEJ7FMHH9gvPPd5HQSNkhLhS/jRZ8j9a9enZLKBhcpst8AWLRauM8YdejEtnmq4Znq8UYEz7irsVB3ljOQdpdqLmQjl+dHonNV07hqykBrazJnsmsYEwIOM785CxOOmFihvUfeAihAwKAYcrrHMTRI4dQxIunztDxhQKSCWD6tnkfFogRAheU7sDglSFehycqHHmiyRdb/Xp/OGpzliowq2dk8m9VBGlb1rmiv6Q06akVr2naZa8G7t8n/pvH9VfckJbzsSX/V08kMOjtYoi99gLJqsrQmwdokvLluc8/mUmWk0sHD22lD3kZn6S9KJFM57pcUMzc/SkS19kmmzBvFQSrel3WU+5B78WlcmJMHqdCgT8EeTB1blK2Fekv6ASGYZdpfYQTGLphbTMRD4/OQzqsXn+F9zpE9yAieLZTn3iIimqdmHb43sPdtvPO/+8lSa12IgMDSbSUBIPdctiwpnkyUkkToqK0tj4X+EOxFp4it7uWTJuDjpqWF0Jq/f4OTv3nWjNHnKj4C3M4wiYGwxirwSQD/QmVWJEhpyu0KcpUilr5XlfYkqhu7K5nWxk99f3O53LJEoTnV4VqenpEJ3UlyEXVjPkBMfw4CAXpzxe7qUXnVfmQDL46vKyD0Bv+4g/faBcmSKIZ+IUn/6/UviBCkDIK6j9j9HVXZ+ZQ/PZ9nSwwVdQ6N44L5xlx6LKPS56PBPeC8T4mcLuOU7xQCzhHvEI9j6rPZQPGKalrrxbgSb041O+IgOir+TuzxzLhlJ1wWZcgnA+DFiFsUyb1nOHQvSX2gau5F00/mzJi6TL9EG2b7bPg8vGWiNSdpT2NmyPkQK54ve3wjm6lBAI1aEeMRasWqXadOlXpRz0TJCJ8fDj+oetsqJgPMvjkQRpyMVPLD4dVgTWU7nJCMtcz5NfDn7hyrJ+yk6E+vF9lLdSuEt3+6RiMD/fdPtFNDhHDndZAxlNVedF0GjVpNbk541bJcHvLCiwAFn0jaElwYLJh8cH2Us5g1+awnOfMAXzzSQe/nwhB7KaPAzQ8wWgz0wVVsa6bWR+13iXp3Qcm8ioMeL1p6CUbeuT4vWO0j1ZF5/WsOCnMPGki1QdK5gPPZpk2IKWlgdsOAwieq1IXTqIQ==", + "layer_level": 1 + }, + { + "id": "18826686-b467-4bd9-879d-73a780854d0f", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "MySQL数据库集成", + "description": "database-mysql", + "prompt": "全面介绍项目中MySQL数据库的集成与使用。详细说明通过Beego ORM与github.com/go-sql-driver/mysql驱动的整合机制,重点解析internal/models/init.go中的init函数如何从app.conf读取数据库配置并建立连接池。阐述ORM注册模型的过程,包括所有实体模型(如order_info、merchant_info等)的注册方式和自动迁移策略。解释数据库连接字符串的构造逻辑、调试模式开关以及事务处理的最佳实践。结合代码示例说明数据查询、插入和更新操作的实现模式,并提供性能优化建议,如索引设计和连接池调优。", + "parent_id": "715db9db-8d32-4ea3-926a-b56c98ea6d8d", + "progress_status": "completed", + "dependent_files": "internal/models/init.go,main.go,go.mod", + "gmt_create": "2025-10-08T20:05:42.1248852+08:00", + "gmt_modified": "2025-10-08T20:16:01.6849372+08:00", + "raw_data": "WikiEncrypted:veTYwq2y4io5qXerCTrkkOuWrAhaS0tPjzyqDTq2Vay5iwmSA9JizrW27BQzawvuWWwwKTBqVtMcPa8A931hekM1drvtyY/U0a3Ubvw/hWNyphDgrlmj4meDkJISiqobL8+GYQA829C8PSu7plz1gZK+M6mt2ep3Y4/L+24ulKB7CwJDMEm7zYcSjRAC1eSkFRY2O3gu7H21I2Pn/Vavn+OIDK6IPknOlVUjqHan/6wYN3Cw9hztjomYiNZDdTykm1t+oBAPPa4qYA0ELw7XE7MDqAxDx7QeCCz0KXk/BJ2xk5I+tZfStWVrDWvBFmgB/B4WokADCF6WTN9AWsR0wHpRcLSqKDN2aQRe8ZdSuWogtg4zfVS/QJAVPlCHDQfp4AVJ7KOuAX/Cr0AER6nWMVLonjL8nxfyzyMn7fkUwY3brCf1+ryQF/LzwnmhLz5Cc0Wy9aV5/j8ETTu8si6nz5Papyuy31Sexy5y/rfBCore1fpAjAgyMOZdc7zsDGy29LOGdjLa5bMR3SSWLG6rno99ksyIRDMTmsGn4wm7NNMtr1ZvNbq0D2yNpMtyr4SR/SS/bGKoLIyegI6WqXEz5HveT2CPs9/vnenlGNLeTXRekydXA699Wx0JHvb+UB/uGubCVjVjJSryJF6ijo9rjLrFihmuhcXDfPUQCn1YjJQQGp6m32+bP6dCsV+wVvUNpSsisB4Y2TMKFVTUaa+FCsSIpbb0A4ZqR1nZ7gDiOj59sKLGwhNcVFDo+RaNEuhnyKykqHj83Pv9V8QakMOXkehrpx6THGVFmSM/84TN/KzJDel0cZwnLxzoe+9r7t3/AlF8pDPAzeFMJFgJUlEkCJG1iayaDNphAnHHqejTHLCnZXIGGk/eDkX1r5GybSEoi6UTkz+88KHdl3WXiPvkOAok1CyO2PaJ2+3fBM0zDzfCIAuLxq/N2dN2ch5Nzf5LjFarm8buW/8fOZqmExaXvNudP7+a6jGZ6CP7ERCxA9yrwuMGGwR0xiMKDcW4lmHeWbT3ofTCr88k3hR4dyo7WWVUE4u6+OU4qNgPtEB+LM21Nw9W3tPSdgM0zKvVmm6c6Z0vA+XbIK7VyXD4sVcEF/B8jlH9n3MBePzHvsoOr5kVqr4bmx+LSndC8rgvfcB7VFOLdSayjHoQE4pkluxtXDENbgFdTyXCi3/I02L5eqQ=", + "layer_level": 2 + }, + { + "id": "0ebb9117-99a5-4092-862c-49ee70ccfee0", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "初始化与资源配置", + "description": "opentelemetry-tracing-initialization", + "prompt": "深入阐述 kami_gateway 中 OpenTelemetry 的初始化机制。详细解析 InitTracer() 函数如何通过 OTLP 协议连接到后端收集器,包括 insecure 模式下的端点配置、5秒超时设置以及启用 gzip 压缩以优化网络传输。说明资源(Resource)对象如何通过 attribute.String 设置服务名称、部署环境和语言类型,确保追踪数据具备正确的上下文标识。描述全局 TextMapPropagator 如何配置 W3C Trace Context 和 Baggage 以实现跨服务的上下文传播。结合 main.go 中的 defer shutdown 调用,解释追踪资源的优雅关闭流程,并提供生产环境中常见的配置参数调整建议。", + "parent_id": "fd2a2cba-0887-44b8-93c2-9cc9e520daae", + "progress_status": "completed", + "dependent_files": "internal/otelTrace/init.go,main.go", + "gmt_create": "2025-10-08T20:05:46.2376869+08:00", + "gmt_modified": "2025-10-08T20:16:13.1309194+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoBNgZfVE6UWPLy7BvwoJmilxKC3nK+Hn9GFCHp3LlMh/2fFOlkKo/0tBDtOTUrZ9ljb+mKhjdJsDFYHHL/MuKc12eRv+grt9cb3fNNhY+gn4HsZIfFLnJ9JFfoHtmtcbxIC9lsVC917nqaTUMhk3Kb2CnAEIzU6mLNyLZ3ZOAboOMv1EHQF+N0Xs6CvJ8TFgImyFrtZl1SaJb/AIqr7Qt+du2pJAgFT9VZUler49LJeTbfZXoEtxDwDXDj/OSK9RSnalmkinxulQJq1C1JpUyDwnyJUWLCVwpnENXdvnVn29HA6ZNpAJSgCnDFCOvZmI14iLIH7R7RGfNygLIshyIVvaJZlaMAubamlvDrM8OSUgUqJkLaEwCrFeGkelRRO+niPR3naoXs3ZpBpTSMP5kEZmVOPvHGz6Hi0N/UZloXFXqrz+/D07L1mZ08CM+HB2QgBdAi2k8t3Hsk4DkwipVPcRGiSPjLfpXnnrbmTpP2i3fuJcPIqMr/3/pigWa8uaKGVx4hxslDLdjbbmAAv7JpIInRja1Se+6rjaQ83PC4VFCI1/HJLmTyAq0OdivGYXp+D54xV14LtW4KAr+cOaB/hFFqijwp+yj8MISVYEqjXhqZkHe3F040/UfbqoFCeoYD44qTFFLDSJjc1Tk4vBKKoMo2ZlgROKdwyN9zQh1LjlG2UzqdNRQC2aBkBgB6IExOZZ9GZFvBTcw3W0gFraMkk5IghKWdkb3IvQBpu9hnvRSG3rdw841EqLW+q5o4H6/EPzy0IcxhrriWwbgSbxXexFEhYGmLNnV2zxtLey3ahQig2n4XqTLPTONtozgVYVrX47eSERhFpKynWQVlJo+N1zlaF7iBz25akniummF8UEOohwwn/4+5YvaILGDkIM0fuAtxGjRCjdc1KbXaDNgVDuMrjE4F1l+37Bkth6UIMhA4M0vLtX/TsWGATX04nXEH/RR080K779IQTU2FFRpLPjiMJRIB851SNF9TcFi2zOppoT6ZeN+z/zdFk0F9Nw8I2bp8BnvAS27oVGqaTOgrqE++ygl2GtuZSQLlg0JqlafZ+YDzhH2LbaXV9bVIUW5qdTAFYRYWxVkxYpBkSORnPvmXKeK5EydFcf/QQpgNc5Cqf2DKg3Uxaamc20qxG7Ic1lBKHxcn0x4exqWIBb4hJrbXE4WHl4YaACWmQGUugIGxkvCd/rLltoH0KdNl4t8qq5LY1s54M47/pkByrs0t9cZRL1EAL30vHkuXfxrEWpgEa5kQY7J7t2wl9dB19f8U=", + "layer_level": 2 + }, + { + "id": "a85503ac-22f7-4a7c-946f-359954121de8", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "追踪导出器配置", + "description": "opentelemetry-tracing-exporter", + "prompt": "深入解析 kami_gateway 中 OpenTelemetry 追踪导出器的配置机制。详细说明 otlptracegrpc.NewClient 如何通过 gRPC 协议与后端收集器通信,包括 WithInsecure 模式下的非加密连接配置、collectorURL 的端点设置、5秒超时(DefaultTimeout)对系统稳定性的影响,以及重试机制(RetryConfig)中初始间隔、最大间隔和最大重试时间的生产级调优策略。重点阐述 WithCompressor(\"gzip\") 如何压缩传输数据以降低网络开销,并结合代码示例展示导出器错误处理流程。同时说明 traceExporter.Shutdown 函数在 main.go 中 defer 调用时的优雅关闭行为,确保追踪数据不丢失。", + "parent_id": "0ebb9117-99a5-4092-862c-49ee70ccfee0", + "progress_status": "completed", + "dependent_files": "internal/otelTrace/init.go", + "gmt_create": "2025-10-08T20:06:11.562666+08:00", + "gmt_modified": "2025-10-08T20:17:57.5854974+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoCfHd9R9oAxkyPItBnu4Jw+et5B3yBxu/abaXpcJpT2OpYOTlDjSqQTt9UmeIFX4bHn6qCdbRkbku1B03GjLzAD/wi1PAhMi80uaSAD31wmE097yPhnpfU+DxJQJ08KE7FS/quvhjPngLe+4dZxwDIrD4pLvJ/yZnFI/8TdnA/7agajUPQxW7dlAOD8yOhxnzr4gQo0/3JE3JrKnzjhnUKLecsEBn9sU+rA4gl1ndsG/wiWmdOXpf1FwCTR7lCszEvZ6rvkaLi1ypsrBcRu378llNkaoQijJVaLjRuYFM8lFS3+7BsMw3eBmX2apEt8feBU1AOhwSjq2asbPFi73CAdgfzCYom96a/1pAPuKyabBUui0pnSsWeH7su+4QapKlnkh0/GP+ugcHBqoFhQr5G79wR8C2tTZUD5bctP+yc6gQucqlGBtnDy+HgioFQGkWDewoGRpFVVs6OGohLT3kBIG5SQ37SOCFfe05E3FGygZpSAVmD1RVa1yzdmT10oMa7wNVV79XtFa4O0qVeGDzYYYEu1WmYmwHj7RLdLtfpGvMUsDfx75igcbzILLQt9ag541qAgQAx8YVUgp5LLOjN5FoHKKerFSrNJC2ufVvN8VMQND5Xiw5FuBNqRpzyp5LwOaeb7rpMjtu3Ks5uynnXB/5ek4wSzkRETayPqwUexS0v6fbc8JnQl7inQUVcyMulBcqSIXMJ3IQCGML7wa4erXyDu2Ct1SjW26buuTMtWW8J/c4Q2wZnnjO6L9cKDxxNC0naQAGOimW+WiW6F1xZ6tCtZGpFWQkZe6qqO+uVT2+8I4xkwPfTRe3i71HlrnD6wRGNTgUckphXflI+cMx7W77UuNGZFhZJS6aBUwq5B3AZj1In5Lu/Ctdp6w97L6CJqCmEeSuY0T0c7dp4GMZf8Wy/wZ/hRuFUbpilg2HqomfeRYhh9Z7ulXvisGVSOEjnQTOt8CkbyG/GZXClVyEqn4r5X4HstYl+/EnfWV3axx0YsY2MxB9f1r9zeCqbI3UbpntlF2Ht7hC+Wrqs8P/NSooxc2vxsNJ0kARDNOsgpNaKfMfvnqBBAdd4MRjRu1sOEk+WxM2GitSkmhhkEHpHwOjoUzVnGkEcAt3xQxC9Jr64oFkrDzpYeiRZabgGK6tSRfFbJOCQHtuzRaGzwbRzfMK7FGYAt9QxWeBxN41HZFurr/dBRgdRKalCUSRzI4IXE2sLf45kJb0Cv3Ywrmp4Y", + "layer_level": 3 + }, + { + "id": "576b2803-bcc0-4769-89b3-54c89e6b7381", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "技术栈与依赖", + "description": "technology-stack", + "prompt": "创建关于项目技术栈的详细文档。深入分析Beego v2框架在项目中的具体应用,包括路由配置、控制器继承和中间件使用。详细说明OpenTelemetry分布式追踪系统的实现,涵盖otelTrace包中的span创建、日志集成和链路追踪上下文传递。解释Redis在缓存(internal/cache)和代理池管理中的双重角色。描述MySQL数据库通过Beego ORM进行数据访问的模式,以及RabbitMQ在订单通知和查询消费者中的异步消息处理机制。结合main.go中的初始化代码,说明这些技术组件是如何被集成和启动的。提供每个技术选型的决策理由、版本兼容性要求和性能考量,并给出配置最佳实践。", + "order": 1, + "progress_status": "completed", + "dependent_files": "main.go,go.mod", + "gmt_create": "2025-10-08T20:04:49.3828695+08:00", + "gmt_modified": "2025-10-08T20:08:07.1086917+08:00", + "raw_data": "WikiEncrypted:w0CkdCdnXCcvlN5xOpiEhEX3U68GI0Ngj6azFMJo9xQD0Nwsj9XajeArLn33w436LuYJWl4xP0dT9zLNODhOpJWtrSnsTOFdbU6xnVdYH2VHdxM0TVYkDKgZ4DwrvVuCMH3n2Ln0dcHA1r96NDT6WyBdnOg8joNlX9Czav4oRaYEd4X9C20dqZf05sPUDqMBk+iAD+QXPK7Oul1xlQpPAgwJ5nXyPfpjzLwu8i6qRiGvlkS9cq2DjI0w7Ncpq1tIF/uAu6Lh9rG9c+gZxgVu7kylK39sk4tndGjN9CYGPm1mS28TvRdAkqLgL5lp3wg1A/dY4553gPHLUa2Z3tS6+Gz3AZSgR9Yv2T9pKH5gY+W+I26tkGst6njmIBiOs9QmrBV09gRAT7vmilTYSzZSPoI9kZcffd19a8sguQyUaBiZ5qx1jp5KgTZCInV7Zuvoq2vHfvDutu0pth226C4ed97O1PjHi8LAFM7pIkTcDvQC0mSylJpeDvdFCdndhZBgsh30YnrxeA4k77Q4MoZxM3vyMKraAsIHFBAht92ll+eoaSQbeaUM+pVNhyjhmUlKy7T0FSPlQKIsBKX6f1/4GCcKEFmXANFniryNSkDgYJRiBv9/y+giTGPqDsVq0RbgDywPXhvduPsiyGGdbkv1E5s6daZJPr10+UORd5l6IWk5cujJnbxLaZ91k85J2GygSkAugJs1kJ5QpTL6l6O1lj0+0JQ+evb8pCfPHi+NBW/IYxNm0+UIML2hW1GTwDl0TTnNo3iex32SRmY0XKcdRoH399DbFPsJxHqtEgi+thl6RH8DT2/RVykXIbxWVXBXx4Z8/lcO1kGty2pgnI6g159jzqIdq4U2ovKSHJE5FUObCxtOIPGcUXCyO2lzAApjNsSL2gAfZBNrHP/VKDxJSj3SPWEvaH14krJIE971JAUBHvNmEa76UbtqiVMEncqA+n5u4yXtd+D/aYIOrAGCLvVHKQZgFmJKMFPh0QrQBexoLdkN7k9YFuUJxKEFfbsPJlNs1Cd9UAHrtPASHas0/BxJqPElUYlTXWimVjbvO+V4cQtYFTM25RrTMrOf0b7nzS8bdZggQZTwLFFphMg/tyzn8MLJBPUMj5lFFmFg2pmzoIJxnfMapbW2x0be//h4wW8FE7H1wMjZz+ipTaorh0smyGzaUFnE+vFiVpK+1c42raKOO8nHl0CziBYRze2U+Awo5+G2kRDj9inJig8q5qr5TtldA/Xa6yitcAWE/bteykJcnSkcP8Df7Mxh6MGYWI9/ffQsQZBp3wbpZJDK6LOZp/GxkghQhIsbrqwNfqQs1Zg04Iqle0Qd+qStx4csZ6ieOhC6LWLWcK2F6438+ixkXauxoR+U5X3d+EcOugM=" + }, + { + "id": "062cb25b-369d-43d0-b6d3-96447d99b3e9", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "商户模型", + "description": "merchant-model", + "prompt": "开发详细的商户模型文档,以merchant_info.go中的MerchantInfo结构体为核心。深入解析商户状态(Status)、商户密钥(MerchantKey、MerchantSecret)、代理归属(BelongAgentUid)、支付回调配置等关键字段的设计意图。解释商户与merchant_load_info之间的关联关系,说明负载信息如何支持多通道轮询和单通道指定等业务场景。结合pay_resp.go中PayBaseResp的MerchantInfo字段,说明商户信息在API响应中的使用方式。文档应涵盖商户的创建、启用/禁用、密钥轮换等管理流程,并提供数据库层面的约束说明(如唯一索引)。同时,阐述商户配置的安全存储策略,包括敏感字段(如LoginPassword)的加密处理方式,以及白名单IP(WhiteIps)的验证机制。", + "parent_id": "a5d56738-c20f-4178-9f81-d01bb592f194", + "order": 1, + "progress_status": "completed", + "dependent_files": "internal/models/merchant/merchant_info.go,internal/models/merchant/merchant_load_info.go,internal/schema/response/pay_resp.go", + "gmt_create": "2025-10-08T20:05:09.9098578+08:00", + "gmt_modified": "2025-10-08T20:11:59.3151984+08:00", + "raw_data": "WikiEncrypted:3KjeyWIVLPDcIZ9hw3jQx0s+bCB627XZhXTUJbQ7hcudYl4JYt7Lk3T/YXtQyNEOebfqZr4ySdA4jUgxPqVciOktb63n1C4D2sywUTrIxWjL6jFk5x7uESW/vsAtm3iZ3zCl+0BGdPNENAZA5RpWB3slkk/29P0WI6LBneZYGk+Ep32ikCROywH0KFSyYsboPKuotCIc2T0mAGOrU625SnKrNnZlHlvCCVb2LVz54P89GOXIW4kCtPQELQySZCFllmPYQA4JvpLOJt+zOlIMiuTZdUcaXdAyV1vZ3/7v65drFs9+KYmivVoPeC5uDSqz+uhIcD6lQOk98CBgVObIFj8kHAhhlFuY5N24uWLzZmyZ0+YTNEeWDCRM0+9iKFKxCQQ5upHjlfQqBLS4VLXO0GDYa98ooksjv/Km5KtSfXIKwOV1dT9fco6m4036seKKRjMCCf8h4Vg0V004q2KNfQqLPFEmmRtetlBNTCsZQmlYRGcNnKJiq8KpzJWuyjaHAolsfgR0DkF2sYdn+01oMcCh99HLFQEnAoS6x2QkSv6XJ3g6rZ52kQKMH5iTyjlahk44VBU/bT41AD/cOQNQHCbvhlZVfeIIRUR/K0zGePr+Ri90L2xcrB0FHlgQbaE7o1zWLQbtCXr0U3CFbys5efY4EscKltGtQPkGw1sn76qvu2kyE7QJPj1RiBJIxJaEXfkBG+or1SCT4lQQYyKszi4zkBhvXjg+mgqaNtfi54sKR3Pz024VWOf62swmjOzczmhFl1LQxZ4MGRlLFEOmpiPTAnmVhphShb7T6G8sHr+8OV4ze1XWrmHaqZco7nfDTnHtfvp2UIxblvWbM9P+3gJXr9U/Yokz9bv68urPaS4HbQKKuJgHQ5mm3M9tVnbFlkvfE+niKh3L51Nhiwo7koWjKbqMnOS9pdbrPVBakL/yI6Xh3+By2JIklY/KjQbNxhF6xTAtrtThMw4TZzQCYVHsRWckQyMQZJLzzGAmPrJ+CFRs11oVySBZSmhZPWdqwewatiD5KwPYjr6tB7PxPmr2Z562DdutatdCUvT2t35el393Pj/2jGj0M4W6O5x4IKGD5fFyPT8y9WrgzC0iXc4cv+ZN1J2kBq5IqlVJSINYV1d5LObBbz6kAAFdvc6GUeUlSx0jhodLv1NpLLkCK5HmATo9JCyVWFG2glhvehTnI1/rY1cMREEdF39Dy1lohP1k0z2SM4ujeDkAB2iMIsbuZ6ceNSRO65YJKNSJCuqSzPn7O+7DbPAPUDjNR6lNOzZf6vJaG4zNqvSPBy6OS19R3HnwdxDrUNzUplyMfODZmSkaHLFTikIO4RgByscl01BySTtgf0ar+ewLrJz309Ctkkj8+HtM5+c6UITyjkoSuLJTrhr6YZuIZ915fZtgBPXMlQrQGxHorXRBqdvlwtCS2+PrePo0Lf+qlFnjaRH1OyscfJJB8I72FsUJNE0HV+dKbL/+a7mCEGyju63c1MTtcg4k3NQl204KLrGiK7YuNui3ptRS1wud7aVxgtOOPUJCwnOxh+2otombyPCTGvLY3B6lM9xYhKq7ygF90qcnBegp1A18fBUiR1M8HWK2", + "layer_level": 1 + }, + { + "id": "fd2a2cba-0887-44b8-93c2-9cc9e520daae", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "OpenTelemetry 分布式追踪", + "description": "opentelemetry-tracing", + "prompt": "深入阐述 OpenTelemetry 在 kami_gateway 中的实现机制。详细描述 otelTrace.InitTracer() 初始化过程、全局上下文 InitCtx 的创建与传递方式、Span 的生命周期管理(span.go)以及日志与追踪上下文的关联(logs.go)。说明 otelhttp 和 otelzap 桥接器如何集成到 Beego 的 HTTP 服务中实现全链路追踪。结合 main.go 中的 defer 清理逻辑,解释资源释放机制。提供 OTLP 导出配置、采样策略设置、Prometheus 指标集成方法,并给出链路追踪调试的最佳实践。", + "parent_id": "576b2803-bcc0-4769-89b3-54c89e6b7381", + "order": 1, + "progress_status": "completed", + "dependent_files": "main.go,internal/otelTrace/init.go,internal/otelTrace/middleware.go,internal/otelTrace/logs.go,internal/otelTrace/span.go", + "gmt_create": "2025-10-08T20:05:11.0709854+08:00", + "gmt_modified": "2025-10-08T20:12:14.1173282+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zS255cSRc7Lla1AgWnUNCCp0pT3SAlQqtM1mavRDSLdAMtw+oajNwFyk035PdPByHpbY7qQlJcUnSpyBJ/rF8hhHdHYX3mPyTtSLEEGr80oDbXf47oVMzchbqsPcBwWhTr+LJKyfp4S2XIab1diWXldjIcfJN0c5B8T8cVXOI9HrP6DGpR0zDWVsfN1DLCorQM20Yj97bgr7lkfk4DYONyfiHh2xOn6srjcmTuz1UXUwrHBqsQ4oY18GRzBF6k/w0Wq0QiZ8Iezww2adbEnLGJfp441LhU4LLjux6IY9tuhIQMbnpcr9R98jWFitbQDsvMlQsJiBUuC1e28xycADMAH8bkK4gFTJe1yxTedXnNpKwpJ6qcRlouk5uy7d5d8h51kEVEcTFYHfSSgpehVD8shGdcguYtRI/hCyXlcLtCPQr7xBgUADycqI/jnmI17zxMucJlimN0J7UtEukbOfr1v9ckm+v51felPtyqYlrHVWJeNhyrD7KlJBYUnZoMNDmPq1e5BEMQqU9pX+5188sVZMLn/7fa4dCQkcWntmzGo/prTrNLLQ7qJSunNaUlSgWg+WIXORc2O3+WNhumLUZUsSioBcZIeW0DxSxujsOK6LqamHvjQGmf0a8/b7NqSmENeL9cfrM6gL+mj7G9IWy2fpGhy/dq8Z/TUDp9CD5Vi/p2YBXaVpceKm4Cbl0gIe1FXEwg9xfoRtqD5LPRE7Yrem/PE/Z/5jDHlQdMSrL93QFEx86IYSGAGoQk3TztOso5lS7Lni38SVlz25SOcojipOLpFrkn0u1hYNFxYktw0KtRmAgxOIcx3fyqJwCLYd3srCEoq3h3c5vuyLS+o26vdyLD4m8UaPjqyfvNsjCCmFBsoJoMrZC+7BSZ37MqgkCiCnyxWwpJWVME7OH5gkZRnwSlV6F0QGFa0KJY3LTSzj35gJi+WSqrAHs8EB0oa43zHvpOpcNvcbaHIK9zpqUqMkJJ95zbK3DevIGBMTdn+ehYSW1N06BR4AF5oyR6feORMh1m/bGNzrJCnOq3aUNBxLIA/FXa/b0VIqf5vx6vGEx73ThIsY5PP1/XSkH6o2dJs5RtEWOgSwVd0BuNxe+VjEgosfTLcTx0VLOyVnT9Q9ExfCcR1i3qJHcJ5/HZziDhuJW0aF806uAG4UKAK3p4P+1FTJlUn5Xka3mkB6wm9gWOAJAZg9BkU2NY02EH2vYYh32wZE7u8VLFiZo9k+tJpHDC1lcD3RN4yMgmLBq4HqmS7s7XcXs/mJfKSraqGXFA==", + "layer_level": 1 + }, + { + "id": "c7928cce-8e94-4629-be4d-3af7f5d251bb", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "查询API", + "description": "query-api", + "prompt": "创建kami_gateway查询API的详细文档,涵盖/gateway/merchant/query和/gateway/supplier/order/query端点。详细说明MerchantQuery接口的认证机制,包括appKey、timestamp和sign参数的验证流程(使用GetMD5SignMF方法)。解释如何通过商户密钥验证和订单状态查询返回结果,包括订单号、卡号、卡密、面值等敏感信息的处理。描述OrderQuery接口如何为上游供应商提供订单查询服务。同时记录OrderSchedule接口的重新调度功能,包括调度条件检查(订单状态、创建时间)和调度执行流程。提供JSON响应示例,说明成功和各种错误情况下的返回格式。", + "parent_id": "80fb1e42-5bd2-4870-8b88-77d31ff5c478", + "order": 1, + "progress_status": "completed", + "dependent_files": "internal/controllers/order_controller.go,internal/routers/router.go,internal/schema/query/merchant_query.go,internal/service/supplier/third_party/pool/service.go", + "gmt_create": "2025-10-08T20:05:17.6697413+08:00", + "gmt_modified": "2025-10-08T20:12:22.888047+08:00", + "raw_data": "WikiEncrypted:l9Ho0Yh0r5bYH9QEePEhke3k2RN8gG332YdAL7KtHYbPchW5eM3k+qEo35lenQE2nhqx4oft+lvdZUBitrIuXQfU+1iktwQUyRE6Bc7n1fYB13gGuhK1M3sz4QVwxdcnKErZG4FBLKWsGrCS6qpr+Mn7rm87oLJOuFQn7CEg8HszDhriQsCptiOxA2GY6/24ZnuOB4LEPaMK1GTdxDB5hHQFW5iMUXuXR0Aq9K9q0L1+Goe5ezSmYNw92YTAwB+iJmUFjj664leLuOuPOAY3Ye/EgRh4QqLu66rnal8yok4CLABJSShhCUQX8T8wXQkc9S2HZ62fOb5GzJT4zUx/Vy6KaBHIZv/3M9wc0wUdgFTGfTAaLNo//xa//mqccFXiv8sxFf/gnd4zFIVBIlJ5e96CYGGPK8m4vM4UyUYvRYUff7lN5++RSUKNJ6Dqt1wwCIkbM0g9TV8z3JIIc2ZntbJ/mvyEhvumd5RwGA1cjEnli8Cbj+1je/dyJOqjY4m2dP17yksS40IigFszqVseWYk/SQVkL6gx9sw/TMtocwZKxFytc5Ng2ZMAhwK7k6TmTttzFY67Pkx8OhyyJ2XmDzFumLSkEznqq+S+sQ6OIWIVieI9j+R1OzS+DyCmktHQF6fBWCAa48wYiX/9zi2wOB7MtM/4exXLhWeQLl4Bby57z+36TvVxhrbLAbqdGer+3DGgzcS8+yasvn5gtHZVGGADCtBQEPSnmbI7M4t8SMh2XeQypL3/t+WCzW3FnH7hmCEwggXYkLvsUng1GT4/q2TU5JDHGIZtbB7zL1R4ooyf4I4SpkA3ZawUv1byVTlZ9RVnPYfXRU334eCRmn2UAd8vkOlA3l6up3jeQuHT/8XhyeBMJbfXF6qcI67zIPOByRGvtvYpR+I+Y1yrVKGAJ5KNQmtHp/2RqAy3LtmvV6mOM9OHCbW/eO9nXcOO9LIAg1aRlmwKR2n1T4ScZ6MIhoe/BQoCR3SzaOMM4z4e8wPZUZ/qTbkD8OZcDRxy1qxcfarRbhSWTQvugSNjYz1qwE6IB3tH8FP2KSeiD3sHz9yq+GLfvkK/H9pwWcieLooh48LzBTfq67m48iegzDEGJCCwwrJE20FWqZME71BhgFDhrm3Xmi8RjyFHkt63ZwJ7BII/sEDrEjChXei7Cri0RCdo3WFY6YJer6pJe1XmLPV69cCxQCShvCaTjWJxNSPVWwFSWLk9JbBz2Fvm+ctKKRyLgOQrOs3YFGGznX5i6vP1/RvjHcuaTc2iQ/hdQNKyUQ+NSoQkjZ4VzEFOTkKt2WYFa+NcRap6OuhzgeeXQVdl71RggYkEqxXUh0b8t3Tq+rhuq9F104O6jBuM2hLfFsrhXSZ6aA+dpgqacf+nBPm63E0hH2nZjaB4AwXrQZaO", + "layer_level": 1 + }, + { + "id": "74304c2d-414f-40ca-9155-fde8c06a0128", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "配置文件详解", + "description": "configuration-file", + "prompt": "深入解析app.conf配置文件的结构和各个配置项的含义。按配置区块组织文档:[appname]定义应用名称;[httpport]设置HTTP监听端口;[logs]配置日志级别(0-7)、保存路径、分离日志类型和最大保存天数;[mysql]配置数据库连接参数(主机、端口、用户、密码、数据库名);[redis]配置Redis连接信息;[mq]配置消息队列(RabbitMQ)连接;[proxy]配置代理池;以及其他第三方服务如[mf]、[appleCard]、[jdCard]等的API端点和回调地址。重点解释proxyUrl环境变量如何与配置文件配合使用,以及proxies数组的用途。提供生产环境和测试环境的配置对比示例,并说明每个配置项对系统行为的影响。", + "parent_id": "53d903ba-6508-45b8-b48b-b3d00d3ed07a", + "order": 1, + "progress_status": "completed", + "dependent_files": "conf/app.conf", + "gmt_create": "2025-10-08T20:05:30.6781661+08:00", + "gmt_modified": "2025-10-08T20:12:50.0934672+08:00", + "raw_data": "WikiEncrypted:aC5ZtUyEKPSxjzg//aVllJun+r82/Gu9h3dr/sudqytlxed4ZV2GKW8hZ0wjnzMJzy4Ohac8ZrkcdbvmLBCy5pE4xUQtFA8hhYdASDqIm10S+PIvKQH44q4KE7YDIXlxN+Acq7MqcTsSjuNjeUEkgudrHx71A/9jkorJHrJlsyk8H8HjNTx3B1fpnTr5dF9AXC2SCUuPtV4IcdofxKTF4Gzt40qxijK/KYQcgiGjoRiS7WtQpx4nokpBQz07b9XY5gdz4j9eb9neooDBe9yFf1110iUaYj0+vO6RdE8Vc7N6KPr0SmPzsdsEIpnlQqnGUTVcq1qqC/mJ0Kf0gBXlEUebNnVpnnvEc3GxiJqtZJf9EvVl8seqK+82dysxvzSO1gjCUdHRDLMtzWy19xmQheL6d1rw6/pW9xbTeExKDmSgJtourqUQe+4qd12Sr/gk9n3h3YyD1EkUl0HpSotdWFtuuZMkJSykI5od77zZVFuYOX4ifOj7091oQgXQxnPdW8FH+GSbp6oEkj28b5Ix125J0z13DGG64dYldw9Pigo2PDxfajiV1TxLK/f55+ZEhAbfYRbeNRsWQb6B1lGln9nJcX4aWwl1wy7ZrPkIifZXW1ststtxYJvYM69iPobCB08/NlwAXpWKKC7qdHw5Uhy6ktHuLf/gq1rGn/qgkMrntoeBcX3jl+VKYdZel24K8tf+28bPgcxCT2WK++j5aL7IGfIqFoBzjri4XL6aFrQ7t90Ptm18jI1aCNovNO9Rih4olxoov3po9qJT7buzqReW8XcLGy8c1h0ab9RAhQJEWZXwTpwmdoc25WokOr9YDQnabpmcYjemIX9JL9rp6VB648dKDhZC5pP/ISNvYpICKz2qDOtmN3mbAE3x8AYIkJCu3QtCD+Kot9dQVbIkddGIGEr9jd933I4zQMUNDW9rXoojIvcFmmo2Qk9V/n9sD6mCYZAL6X9ntdh8YXqWA9oRmixIQVKdIxPDxrvpn3yKWI1Vmnx01Ez14hN9mIRs3ffyJbnQ8MwI1msWueCyLvYvXMHzTcockWRjnR/GmQ86mSvM/cgXfaEBmRZooGZqeNyKse5LMOZutjImuy47ONdYYccnj/L9qDyMyJjBN3bFs+BUItf8RKVHWhPwhcRyBQ1kwYSxU2yR+N8kyohkT1042nQQfOzDboweuTgAqpTjf5pEYXyPWoELgYz/AHJNVTlRTe1mdBgfgbcsa5MsRjuBTJNhQFIJZAdGZUXJ4uzZi12eA8cxqt1UXGBUAClmXP4gxOf/8rArpxcYDG9p49F4xyT18lVE/lZr1gqsg14=", + "layer_level": 1 + }, + { + "id": "0d7875e0-1107-4966-8a99-a6d24685c88c", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "供应商集成架构", + "description": "supplier-integration-architecture", + "prompt": "详细阐述基于PayInterface接口的供应商集成架构设计。分析supplier_interface.go中定义的Scan、PayNotify、PayQuery等方法如何为不同第三方支付渠道(如爱博、京东卡、天猫游戏、沃尔玛)提供统一的接入标准。结合具体实现文件(aibo.go, jd.go等),说明各供应商适配器如何继承web.Controller并实现接口方法,处理特定渠道的认证、请求构造、响应解析和错误映射。文档应包含接口驱动设计的优势分析,如可扩展性、可维护性和测试便利性。提供类图展示PayInterface与各具体供应商实现之间的关系,并给出新增支付渠道的标准步骤指南,包括注册机制(GetPaySupplierByCode)和依赖注入方式。", + "parent_id": "1ccdc69d-fc3b-4d08-9be6-169095e4a163", + "order": 1, + "progress_status": "completed", + "dependent_files": "internal/service/supplier/supplier_interface.go,internal/service/supplier/third_party/aibo.go,internal/service/supplier/third_party/jd.go,internal/service/supplier/third_party/t_mall_game.go,internal/service/supplier/third_party/walmart.go", + "gmt_create": "2025-10-08T20:05:33.9890818+08:00", + "gmt_modified": "2025-10-08T20:13:46.8772551+08:00", + "raw_data": "WikiEncrypted:ywogS1mtCJIl+oV7mNfjwDV4dOWErrIfn5VN3rZcU5zIjilGDlComIcwwDZI+34gNPPMwtnac1GAjEMjy0hC9xOCYI0xdruHOD03uXFp8XIAWIsegStP4REGBbmH/L/wOeeiS7zf6B3e5QmC0ktLhYk7pqjh6FOf3uvPyT8dOTMgwUS1OA2I+riym/9wqDYEFak/Xwdept3NvSE+SVNKbk3Hxi5b3/MFw5MJF6gdAJr5++Liy1daocRXXIW5Ym0ZW+qUvP/VSGh0tFuJLpKHVbWhBKrRPXQUHcfYrn8knJomzT/926tME4M+ao+tDaMDYifqELysn0AP5+zUmRZOl4KXUi0ZUk1GOGV0Sh2xJv78e4zm8P7QflCuLHtfsO+TX1Nc9Af55DpLU+7SWk1/e97KAcOgWYcKEBVHriAxnzKf9yy0Nm9hz5lBDc5jHqKcjXCuPMv65Pyw8+UnkFs6X8sv38bvLGtOTmYqFuNPYYZygIfw5UyRI13n1iuVjmXwKzwjZoyXc0MjmbtRcYxUaePR+0d0BNLaauVLEOWhmJplKsyeCJvtyMkovdSMxYmwnvwIEP9kKrRrL1Pm5Z2Vh4ePOy0VWaFyF5J87jPJPDBkQIAXn/hIXtcD6wbpeiTBLOxud+M2NWa6ZizcNl4Zef+YpzDr2niKho+8DQYZpXFgtNmRj7cM9nOVr0wj9YrIKvj9tpMixjz+51oMV26/G5gZjwoPl/WBK1sQOp0FIKI5vRWxntVoSgQTsrG0xjV1OUbSanOjvbfWFH3YEm7GO90orxnnDt9ujvVVs2oTpjnFzU5a+s3DRl6TxrUJe6cvO6OucFGzSIdG0YX2pL0205LtIwO+wGt8FUxF/5JWnt+Qw0xIO2bLNc4N0zfRmXmMaRkRF72+CuFlGhDaemazh1OM6R6697DnAolV/r99+iSJJrHoiY0qY8sZjWn48waBYPNpWJ+VaW6TZ7lb8+4Af6SkZu3S8jpH0pscQ2KTpq8pMJBoafKxhn0dIfxCHve5a96Ly9PUuF2JYqfRXZolmEL6GColhmUEI3uKRS/XYIGZJyzXgqpVQOskgU7kuoamNye15tCbrs+fqNcM5+XgdgnARMm/1ck0khmOIhg37hY6kFW0cuyl3yth2hsIPPcql9z+Frr/Zmd/Y6aQg2cWYKCUt5CoO00JSsdiqAn3uMcVuG+I50LdrabWjYkV2xRTagO5libnh4qvDutNVYO3ruMgAN1J55kUAaghK9YYhgcw0nAbSz2HC0U+B+1iAemccnEZFSw3iaUrSgV8BOBIbU0C6FxbELNPsxgl7slaQUFZtfK7kwGKfjlrd8HNmx+3Eqs4AG9sgQvAmjgoEOxY+EJri8lY7g9Ut6rHKaaMUivhywpPo41n/b0ZtfE8N1FGgxTnJ4MCvN3q5cOWsdt1GGqEoOyHbUeodHF4oK+9iMHEse9R6Pka58yV9rAJbM2PloCqk+vyeRjmKYm17KLCN9aJ2L8gwM6XcD5AGzjApqF+OKzCNgJTdl7a+rv94Bw1+scEF56CDhldSoDOI4S6+qdIUN6A7RS9xst7LQaGbwOOXHWzxYOa9IKvgG9k41DtMTF3ItGD6Ra6Pfd2CJfhrCjDW+rClHvmdVy8ArCx9QvU9hUxjxM4oZPpy7B8sWRCF2EgVGwzAAX/U8qOdxw+6Vsy8PzbbhGNmDSRazuAj++0151QsIdXENeoMfScdnGXJOVdTCnUibQs7fYabLmVdMz6PvliOmUuK6dwwdk+0+8=", + "layer_level": 1 + }, + { + "id": "7f560146-d4af-4131-8722-dcf698604b6f", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "Redis缓存系统", + "description": "cache-redis", + "prompt": "深入解析Redis在系统中的双重角色实现。详细说明internal/cache/redis.go中Start()函数的单例初始化流程,包括sync.OnceFunc的线程安全控制、从配置中心获取Redis连接参数(host、password、db)以及NewRedisClient的创建过程。阐述Redis作为分布式缓存层在高频数据访问场景下的应用,如订单状态缓存和商户配置缓存。同时分析其在代理池管理中的状态存储作用,特别是与internal/utils/proxy_pool.go的交互机制。涵盖键值设计规范、连接池配置、序列化策略、缓存穿透/击穿防护措施及监控指标采集方法。", + "parent_id": "715db9db-8d32-4ea3-926a-b56c98ea6d8d", + "order": 1, + "progress_status": "completed", + "dependent_files": "internal/cache/redis.go,internal/utils/proxy_pool.go,internal/config/cfg_model.go", + "gmt_create": "2025-10-08T20:05:42.1421683+08:00", + "gmt_modified": "2025-10-08T20:16:35.7591809+08:00", + "raw_data": "WikiEncrypted:dAMSC70bWva9SabC1uic9nJyKwHAU6Vz8XMWhQC2fsd8tVyLbBciJVXYmCmH1Ok5kX4CcQ9stt08MrQ5/ThRrDM+v2SCPpgp4Rafg5KxCF1fPFNDVXxBNZ37GptrzzjgJM99R8q30+ZFLv7KbXkbAKxbkockVkEmL47IPcaTB4KQGIl0uH4TX/HF3pCq+S3Q0tuB3eZC8bjsqKbl+5IeedWG0KIv8rFAUZVgH4KsudB2nCjhiO3iDTBbJyJJzIIaAoUxJ13ZZxE8IkdiBjnXKUhU1G5hxsgzCWvPHro84xG/PVWtn3FZMJqD0/3W8md05WDT9/bQ5O3WpeJhB0MvWfiTpiEb0q+TfDOQ5ufOTDYYs8OFevJ474yZzjDzEhlreY0GCRgXFXEspvBOK/kR0XCzGg0QBu6FsrdoB62vcRXCuFm0Yu+LmESviXgzWmNL/LQj2W/kfb/vzTzDWW7KTua5QJwKc7IjgEnQGpytTI+uAfWogK6x4LuoDm5XIH8Z2pIMu5FaNwEJfzRh3ug1xk86qdhb5TGnCN1w/NhiNkHczNnPwOaQB6VwWPyO9ehVfKsPHQyTqOFEXvxqhciy6iECEBiiyl/c4/0S3b3FPa6NtujCxQY/nb1+6GGOLECBttFp37DHzKsXOV439jZuHxLSUpyy1wgWpfEipayjIffK9qKXW6B4hQ1kAr6GSh6vgkAgn/K+wt8nlC/JO1hD0lbENKKKhkjUM+eXCgWvNtS2Kh4ThFs2ZUr0mB0o9jmwXhxUHQf0INId/Bw0WnJZsJnjWd7/cu76sNJBwClXzo1uYZaQirUv5iizms72L+OvjjL8UKmcMHzuYgSTqs5D0sBYvU4ppkVH3m81hFft69rcUXad5E2A+kOwOvaVAUjC8J8n5mWX/g0kF/BAriXvWldXEKG8NsUT1zo/y2xHvBUltzD/9Op7yZpXpCvVi8nQ/1T38xUFCvXd3z9knvnC8uQCdAWfx1PW2Pc81yF45Ca6vVg6B+xeDb71DBS4G6YbqgHNsZIlddGgdN8FvJVYp6VzMi4kJsWv149tr38aItNf6SaJC4rGMHRwKRPSybHJLSfkNeL6kLfjEfmI2AYWjiuiVroia+ccXaO2TjmFvx73cid8zpvqgpzGjczGQ+zHLjP3na3Zn1HPfrH5BzqcVmPNfXrZF65n6PXweEBiv2at0XuXVgabpbjNq4LJ7sHQqECC0opsyBcQKaAFNJSEnj5/mdsklemuJDCc5yxxnXDDNKZj3H8A0EcVwrcsKTHdHpqztexy5yT+EvtAUpvd8A==", + "layer_level": 2 + }, + { + "id": "b99f6bc9-1a5f-4e15-82c4-3f4c27eb0724", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "HTTP中间件集成", + "description": "opentelemetry-tracing-middleware", + "prompt": "详细说明 OpenTelemetry 中间件如何在 Beego 框架中实现全链路追踪。解释 Middleware 函数如何作为 Beego 的 FilterFunc 注入请求处理链,在请求开始时从 HeaderCarrier 提取上游 trace context,并创建新的 Server Span。描述所添加的关键属性,包括 HTTP 方法、URL、状态码、响应大小、持续时间以及客户端 IP 等监控指标。重点分析熔断器(circuitBreaker)的保护机制:当追踪系统异常时,如何捕获错误并降级,确保不影响核心业务流程。阐述 defer 函数中如何记录 panic 并实现优雅降级返回 500 错误,同时确保 Span 能够正确结束。提供中间件性能影响的评估和优化建议。", + "parent_id": "fd2a2cba-0887-44b8-93c2-9cc9e520daae", + "order": 1, + "progress_status": "completed", + "dependent_files": "internal/otelTrace/middleware.go,internal/otelTrace/consts.go", + "gmt_create": "2025-10-08T20:05:46.2609179+08:00", + "gmt_modified": "2025-10-08T20:16:57.8793561+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoD6zEjjF6IpmyNitJcpys34AnG6PRG58wTvBVd5Pmm2kROkOC3nqxrdiJia2ZwW+aVBJ5JJGiU4dkXutD2rh+bzlkJC8jWdsGWSaQ5H2oLCwG1vWwVltRVMhJIeWC+HkOIszmF8dq+A2Dcs3KcbVKyNI2LkVVZxJKR24qDp6pYAy6UD5rjK0NkDibKdCG97UReRwNhjxHVv3yuWh71x2xGK30jd30THXNZllSVK/mq1Q0wR67edEGouF2Qq1FaFMoPk0c4/4scaTr9j3VhDDStjmQocADwqWA1f2BaiugKC18o7toK/YUt6rFI0OTsEIjPrBWrhHyigzdgMLv/DPCVQeqykA+MGwtdH5xDA7fov3VKZ/g/EU5+qGLV6lHmRTZxgX0xfVUxIC5/mRjWpmx4Ea6BGVQoGchl83b+jQVflxRo8OsHEnHhvKAc4Fy98Kr3CAczCWk+RbjHZ4vxJ+zX2fso5oEFoHDVCbHLxmoTwY7L30k3cnaRRs4nbV+q5dR1hnR1rUkuLWp6dGEyazX5pclE53oHUC3C24bUznMrjadu/OTBfPQRWkJ+oTah8/sfqkDXDMQHIZr15mnmEmHIqm8U8FfFJYvlpe8/x6yUmjnsZHLapzkozleobu1ctPtRnCajlLG+KxR+Tuhogz3ZmAQMVK/oUbQOsREmhQ3V5OEXbgVR5tGHE4ECXXPyjbCE9qYa9F4DoKy4lXKYtMgJqxoNSptSO8Y805S43oqbpFRQcQ/1ZQB7/h5mpgkGLLAIA/sTqUZb48tY51biZh52YtaWPfON8z53Ygv/VER+xTHL10Dvo7iuHl8lv/Oe0j2RTnCSyEbXmRNlyo7yJhN/URs9fkzeyfxx/zD+htV+7bBea882sDmhQ5YOK/K9t6noEg9jnDs9SKto4x+dSCscWRSzWRxoaNLyqlQDxYg7NUBTxLtKTFwVoFqmrLnNkt7gtmXaEkZYTBQu2r8GV7SeblWXIjkCdneenxalzaJSVMhqqWniDt6zTWUEo89cFw22957WTqq3rxOfrGpUu2Lu6Bp9iedb8hz62VRPfcijqCJdAp1uuxP2XH5MPnp/jkRc/SfAJoUVdA/dWH3vWBxLlibKpMkEtgzx4ycF2CLy5l5U2GnX2QjECByFOAfRibSQV7fwWQjGPr+sJVLzql3c1DrR3TwfpCxT7/Qcply20ElP8wHel+1rxmvvRhuogQwtKozN+LI/DedE0fZc22ws1bM4gALZmmc/YUMY5hUGgyT//b5ObXlnRoX58terCMfojZ9e9fdXXlP0Cn6Ir4ZH+cJR238qrbArW0cReXD387k7xiLlV++REBpyqgCAg85KT7NPgVp0ibNSBiiGSrhpkYA9V6spiI1gnMGYUIxkFjkneCevCZ1WLIX6cBHf3UP1hb6KjvDfc2zRYl405W471", + "layer_level": 2 + }, + { + "id": "00f89107-2ade-477a-b10e-0c444161fdbb", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "资源标识与上下文配置", + "description": "opentelemetry-tracing-resource", + "prompt": "全面阐述 kami_gateway 中 OpenTelemetry 资源(Resource)对象的构建过程。详细解释 resource.New 函数如何通过 attribute.String 设置关键属性,包括 'library.language' 标识 Go 语言运行时、'service.name' 定义服务名称以及 'deployment.environment' 从环境变量 ENVIRONMENT 读取部署环境(默认 production)。说明这些元数据在分布式追踪系统中的作用,如服务发现、监控聚合和链路过滤。结合 InitTracer 函数上下文,描述资源对象如何与 TracerProvider、MeterProvider 和 LoggerProvider 共享,确保追踪、指标和日志三者具备一致的上下文标识,实现可观测性数据的关联分析。", + "parent_id": "0ebb9117-99a5-4092-862c-49ee70ccfee0", + "order": 1, + "progress_status": "completed", + "dependent_files": "internal/otelTrace/init.go", + "gmt_create": "2025-10-08T20:06:11.5699417+08:00", + "gmt_modified": "2025-10-08T20:17:55.1134883+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoBSpNXDbJChStEUz/jhm68zL/ANbfI/y2zT7x32t0Vfi0LRsC2xXbr2+POukHA0Kcq2TwfJsDhWBc8H9vZOt0nttf5SDMxFzrKu6uJgupH45V7WOr6tInJYt7lZuWEnewpt+1EBpgzYQa0MnJlDYouRumuBtY7TU8mZlpeNKQJtJxIvjTEod/yQ1ijfeUuDTEMGAUs7QlYvSMuq4+AChv8cmeelrSwuzAiPSRVGISXYRRVldgYZPN0HssWAwGoyQHyDZfCc5jiTjljSgHWcbUBZE/UlRUddSKB+mSJz0guHY9Z0cPS4NTZZxPPOTa8RzsB5SXRpx5sZDD1BHEODvjd9+k2dmgdu+xdAiX/xF1IVJ0exCGkPVXC84MMiFLhUsJpNMx6sj2YBQGhUaETnTHSu4kJYVtBme5SdF6NcMlwe/WkyPANWF/qB+l4miChK/lUX46paZNBdXNsHu48SaZXvLJl7hriSOPaSsPgg8hwNaOt7EVNDILcu2xGQanYTbCjeLGyMU+lVOoWt3bvjYH1iujWYhoPaPLLMbUCNpbizNwaTds0BP9kBIvFRwKP1fzJum1Qg7tCdrSzjJ93dpGVEL5ZD3H/zvBbaBQGyJ6lQJyO9tz2uhU7LY+FiR/NfphGK8PXbi/oCf1hLxfamcI71qTluts/GIVM8XbbNM3++jiwqas9YPQCoQam/lismditjBck1KBcn51e2XbcrDkGwegBXbxkn4DnkyXfJp0IHJR6kdUqAs4bA0U1mUshcfN+D4qTtwicGD0ktJFVNzOOJDg7x8iocGq2eIUPA3M4qr6MZQwWerxlrB2auVEJ8HrVR4C4C/W8mQZd1uXr2JKNbsYipKPxqYldmDy7sIV0CJsMCUSkZuQZFlQDRtJ8ZxJsG5y/k3e1q2m20Z1feFq6rvmc3PTZQ8281/LRvfhC8OJK7AMtTG3TuNkvdf9JKu421O5JtczoDq1RJzdrX/yMJtRr5+xYJMj6udeUBuCPKIdluPHJzXnfJwHirZLhDQE4/ALS4d1ZIhe/uROQvbmfzVSRb9H/YZxZOeUFLaMREAuzuvAvZGgcX153m+SuXbx0cONwtBW8xTK7SBNFJ2D0Wle6aLHeu03OGwqnWiY4AtfLspvKMEKE/0uE4pwj+VyBjUMHFqL0m8m3ppXIOaO0uyEDSdwqQ9V3gu6TGpRUswGUMppuUfm3F0Y/WX/XtprlIOjPHEg6SOATvlBJlvvDsbO/94wrLc4MaKIp4JOujaQ==", + "layer_level": 3 + }, + { + "id": "80fb1e42-5bd2-4870-8b88-77d31ff5c478", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "API参考", + "description": "api-reference", + "prompt": "为kami_gateway的API端点创建完整的参考文档。根据router.go中的路由定义,系统地记录所有公开的RESTful API。对于每个API组(如/gateway/scan, /gateway/merchant/query, 代付接口),详细说明HTTP方法、URL模式、请求头(特别是认证和签名机制)、请求体schema(引用internal/schema/request中的定义)和响应体schema(引用internal/schema/response)。重点描述支付下单、订单查询和回调通知这三个核心流程的API。文档应包含实际的JSON请求/响应示例,解释关键字段的含义和可能的取值。同时,说明API的认证方式(如sign_verify.go中实现的签名验证)和安全要求。提供客户端调用这些API的代码示例,并指出常见的错误码及其解决方案。", + "order": 2, + "progress_status": "completed", + "dependent_files": "internal/routers/router.go,internal/controllers/scan_controller.go,internal/controllers/order_controller.go,internal/controllers/payfor_controller.go", + "gmt_create": "2025-10-08T20:04:49.3906967+08:00", + "gmt_modified": "2025-10-08T20:07:10.9661719+08:00", + "raw_data": "WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPkUytUlTK+XtmhJqDmkbtEHUInBMyGJmK+1OrYyJNWBIpK5MqFOE4zxWbADYMfqE5uPRF/+D2A1GFKxzslzIffU2ED8IRvJhimcsWXs7V10I3YbNlFyQ3JouxPFe7AzJUW8ZSTDXNZQ2liDrzTN77VbKrrQBYsfAGuS7PjO7E+mjbY3f52UeUhXzrWUYj/QANNe69UbPejykm7kMXkNLU8irJ2a2Ob+Z3TTi3d9jPEbDzGHwMdMC7Tp7iimiDBX8+UCUjmbbJChUCw8jQRSiEGibbN5g1VSyzv9cLGWsi9hJxL6hxjG/FJrQH4sOME/m5ZzUnzRB0+I3+5cWyOQBl5O7yFLgn52QKOR7/UxYEWZ8uaBBEfsHaDUcVrX6jPmUqKtKoWb+KFH8ht4ElkjHdEbSEYZ1v0XfVXD8z7Xoal/GPY/UEFCOTaSAu5S1cv4ZLSVExMTk6HI0A1HIuTwjXxHDxRggvOKxEwyWXlCSvParfwK/ro1QFGt1BFE9dULPHDqS7XcJglmjH2yJmvO+i/7gJmAD6ycpIOBw6duQW5la7IdQtMcxAWemBZwhfisVKCWq1w7Yi+f1iO89M2hGjZTxR18wEVtbAGqJzARA7ixJr8gzjjjvoEUDCS1DdrVTomxE0/PEQtLnvp3kkKR/4oH055vAZmLkm4w1HWCJ2uu+593tmRfOPXk3UAklo+4XG+w02eJQhhlWwvxeJx6y8UyFZeea5VazybqnCajdRHj1ZU5MP2VjdOKAakPBuL3i0FIcvn6sPhHYa6N5w6M6306KBA259KDDzwJeZ6/9lYOzWM+ahsHOfJoNyLu4ONthaoeFh7N6TWKJBsoemN/6wVS3TQiZnWZGFHSpf41naMpLlt2PokBkmDY/6mPj30H25PydZDzG7WehjjZm2ovYhbFXJweQd1Fb2hV1JRjZC8+DcsY5DnZqf12yOSLglqJquU0tS6O7pKtN40WLYyI85QMHQIbpFZVW9fEnOUNj3yjJBxXbzhZLgiUyLLhSJIdN1m0ENI8xotulQ3+GJawV5IfqTCMvOvPkTF9zY77r6hkLqeu1SMEUWjMiKB1Jej0hWJmK1f93krh5tvxqqS44tAON3nsntP/Pxr2pS88IcBquUcNq9ooNrX8A0HQ5UfF56By68H3r6jW0xxTGCmLB9hwz3rynLNGR1D56H4PHB7+Swy9AiXR1ZVYNDk3ggfjFpRT2Yp1VNuhCLq1j4g2B5tWqY+kUfDwIYjlFVPsgkgCJ8Q6vtXQ2pVNY4iCW2EzD00rqQkxHwFVM3trdhemLmzs74kdOp2TaIiU1ChwW3okbHdoFXvIXkvcPDF+UWbhGj03XKQsKMaG7vEozDZLF3DRRVCWNacy6bG+vlmpa+uhgrUVvDg9OYhuZbOQgAG6PFpNfeFmoftHn24ctqkfTrzjFAZCzs2xk5RbYibRu1TXTQled6EdXsS64diVD7KmW3T3HPWTTzavVWnqYxu7rS73JQ2fvQrM+juTZG9+HqQv/4BjSmUtT4Al9lWtV+/vy235vXV5WhpyrqmRalCcTCpOQwAX0ydpdqumKP5ju25UQRG/Da0pswtJF90T67Z5SXg=" + }, + { + "id": "316c7f5b-5e53-4322-9376-f94f1cc1ba37", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "账户与代理商模型", + "description": "account-agent-model", + "prompt": "创建账户与代理商模型的综合文档,重点分析account.go中的Account结构体及其与agent_profit.go的联动机制。详细描述账户模型中的资金字段(如Balance、FrozenAmount)、状态管理以及账户历史记录(account_history_info)的审计作用。阐明代理商(agent_info)与商户账户之间的层级关系,解释代理商利润(agent_profit)的计算逻辑和数据更新时机。文档需说明资金流水的记录方式,确保每一笔订单结算都能追溯到代理商的利润分配。提供账户余额更新的原子性操作示例,防止并发场景下的超卖问题。同时,讨论账户安全机制,如登录密码的存储加密、多因素认证的扩展可能性,并描述代理商分润的定时结算任务与数据模型的交互流程。", + "parent_id": "a5d56738-c20f-4178-9f81-d01bb592f194", + "order": 2, + "progress_status": "completed", + "dependent_files": "internal/models/accounts/account.go,internal/models/accounts/account_history_info.go,internal/models/agent/agent_info.go,internal/models/agent/agent_profit.go", + "gmt_create": "2025-10-08T20:05:09.9169119+08:00", + "gmt_modified": "2025-10-08T20:13:19.8865856+08:00", + "raw_data": "WikiEncrypted:3dIsHCE5EGeVKP2C6D6lOG7DpzlCciGgDXyeuMbTmE1WIYUNyK5FOTQ08pifOdb7S06M4Jo37b31e6e6KBgDHtoKWhfRqraUCev6GkQofWmjG+gbsxrjgnWOEtBWJHH2mK0i/k97HyaF8t547pERtkVpDZ0SrWobEEXkgbnva+o5TnBqNEE2isQ6owUZ9bqDyEcspoX6lfqL8WkdbdEfW8dmuISRiPXhe4u5Bh/C5gScPFPoAgE23w/SY3esazX32NbwNQHbJkywtNQxUigGC1/ZijRyuYFc4ENJ2WOHIAfA0kzHWGjSqw4RvJswc0wwMSoBmXDrANvc8wYgfeTH/GsnSn9RWooFcrtsv+YbTMfIAJa+u2i9sIwGbO1rhT4CiXFMiW3MVIC4NdG1HIllf9r30a4nDqHC2lIWylH7XPTXqPlo7rvfEz7p5MIJHzbZ1Zo6SyEhNbNl6TlH19zE/vyDYWSKN06L/XVZjlztE3YFFeawngMD+b5RnhheyCeeJLO8uf/gKIGD4jWkABkswIn10pWlGXRXfVXacTucUIS0st4A1WAQ1xwC6G5JWxSaqZJtj3g4bLY2e6+Sc8Am5lT7+VI149sGR/QNkw5HuC2jwM8RRdHPpyze3l7pHyk0D8B5rKcrDUUUXu8QKxCIPcGpNAEpPCE49uXRu/N9KLlmQESzdOusKLhQiXG9jK0NLhRlioTNTjtWP6Ejynav+kb/361mvzJy4SdVg9OR3/WrKmiN6Bb9Si8wiwvwcQdetChmX83aYfQKUJG7jEvKLj/pvcom+bo2qwTAFB9OlbnrIyVb0h2gEWufO3lfhdrYPk5UJRxJgMp3LZ3TpTEo9dN41w7aVTpt8OMT39nnkDk6lC6wNbtmJgZglz5QdvR+VusHQWtiJeGX92Lp8gZQr7ttZMH7VrMxdfY79BElST9D0EqxgM6MusjG14/uUYkXBlVil/iRlPySO1bdZBIB/Rj+DOtJDB5nk3Ev2EF3xUSjnm9fQRtbnyBcAvJg/uCXeQhMXEAbr4575f61JSYMoD614GS0JapQh3wucuBP2bBjP+Sidcho9gx7/5t9Ir0in5DxXivTVKPP40R2/ttNUPfIjlZXhdUXLXvll52WQ+7DcB+ecSDHHrYrlx/HRr1lPcUdokdfD/FKrXRTNIehSK9lvTiTXM0W6VYm/dzh5RVllsWVCZ5rAX/r+SLfy0UGYdYAivEY3KK1Jy8ieXqbFLrJxr4Gt9f2FEhjZSeKYbOQGWl66/GSS/wQErqz2YK8KWl2JwhrOupYjU6lJ9C8/aq0x8ITEbScXODqNs5eElI/oBldfFih3MDWuMU98pS/DpTTAFZJEKnAYvY4MpfPZ89ZvsVvoVNZ5SQt0CG15NZhDXFa3eIAAOhdRfPbE5zj9X2gGj4vW6EKzc+6AYkQDNLyIt6cKkNrYrVSeGZ2x8GwSYD2bPvzs0bRM0OMhse4wdLhW0EDOwKPrdd5UGagc3XOhbzINiAd5rnRpuad71eCnpy8geDUkX/XDVB9gIq65XyuG2kgwBZXMIXUorWPr9BfH5kZ4wWLV8HgNTpCXzJ6GsX+DAg4EIx3np+xGDRKNuJ2zY4U+aCLlIzJ0NZXspiDSfrA0fQW6Tn8SmMsua8s2ZK1VvkQfCvsCtlSD59dexHjZ9Oc1mGY/bL8gOyvkf5ljnfEnK4xsSQHTeWdD54=", + "layer_level": 1 + }, + { + "id": "715db9db-8d32-4ea3-926a-b56c98ea6d8d", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "数据库与缓存系统", + "description": "database-cache", + "prompt": "全面介绍项目中的数据持久化与缓存架构。详细说明 MySQL 数据库通过 github.com/go-sql-driver/mysql 驱动与 Beego ORM 的集成方式,包括模型定义(models/ 目录下各实体)、自动迁移机制和事务处理模式。阐述 Redis 在系统中的双重角色:作为 internal/cache 的分布式缓存层用于高频数据读取,以及作为 internal/utils/proxy_pool.go 中代理池的状态存储。解释 cache.Start() 的初始化流程、连接池配置和键值设计规范。分析数据库连接管理、缓存穿透/击穿应对策略及性能监控指标。", + "parent_id": "576b2803-bcc0-4769-89b3-54c89e6b7381", + "order": 2, + "progress_status": "completed", + "dependent_files": "main.go,internal/cache/redis.go,internal/models/init.go,go.mod", + "gmt_create": "2025-10-08T20:05:11.0790017+08:00", + "gmt_modified": "2025-10-08T20:14:05.0406994+08:00", + "raw_data": "WikiEncrypted:veTYwq2y4io5qXerCTrkkE+olzqNtNUVmkVTDuTHLlK0F25dp8+akt0Je+bfNZcjdOyycHvaSL/ZfcM7nhd27KKoYh51tjBGZdcGx/3FA7Hfs2MZ7KyzDPsgFevcdKUyGudiSk5WvcEdsfE3v4x9cKcsuC3LtYTT3Kmf7W7y4s0/79F9Lm08KCuSa3czoNos9iLbUwx99A3E8/cfoNA6cjQm7bD5GuiybQOvo6dd1OGe565/6CYmgqZp8cetjqf4FdAzQRRMSB9NMDn41crnsBB5oYmClrq40pXIGfimq50WTVhBKlmCh4vUOAqlOWKRp6MhH0/GlM66DwizL/Bbzxmzpj24bgFvmt1Tp9F7tvJPJz9aCZYxN13vd7nMHdMTEP+n85SUjlaTqJLhqc1giZJL6Cy6aM8146XjWdaBUEq5bbriHD2HEyMRdswFeik4J/z8LhkADRaB/484L90EkotBnzh2+EKyoxWOhqbrsGKvSOK+FEK4SWiyDuH8vVYMzlr26yLhfwRVVhkpLl4zwM6ygOrOSyfq66EjLeKWHrxrqEx0MkSmHJdGktvXHWlYg52qy4sWnUCsqfYBXoxmRTdbFJaUSUWrgy12TVpkzTp5Rv3vxL731TDYAqRZhSgqAk2Li0j1LImW91iOrx4/wLe0VhjnbBmwoRyyG7wY5rJgcCE/k9jTlYxnwLGbabEJtiYD40hMaKLEgtmHrB2cO9dcbcAxlCuPJdkT5h1S+p2HBTZ7E4ns0qZwpZNxIan4mD9H1eJl+2cPO6RuSJGfL4oeZsYwNuaPV5msTWxHP7XY4JARUWrJwGGV6Ox03hbfhljuo99sogQab+3fmQqiTaXbIT/X59QtUB/L7E2Q9z5vyCF6Zf4ucb+GzORPQP5Ia4GQ3iNvK1v4HVHVylQlCIrGPw0FPfG924nbT/OzRccT6IS/FnAIffeLxqaM9vKtGIfIJ1wxYTheyIZrNS71YFQEVVvaZHr3he2yxJlfEK8OLaU/IX98STayQsVO/F6Ee2Nz42w/IDINAYHSUPcaBEOiVZ0Y0lZAo4F+5tNnWwSCDJ8GbNMRyzPFKEcORapvkWbxLJ3lQmEZZVRshT2Tobl2az2fu8c8Z0/5KEq7It8VgrHiRmhsuGi2Ya4ScGoPP1BsJxaJLW6/c5OJTGSPoBQQ8vJ19C23ZDmCHEQuA25fnAfk6azkg+Z8RQ5kezP0", + "layer_level": 1 + }, + { + "id": "8600f0c5-e3cf-489b-a029-725506750564", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "代付API", + "description": "payfor-api", + "prompt": "为kami_gateway的代付功能创建API文档,尽管相关控制器代码被注释,但仍需基于现有代码结构和命名约定进行文档化。详细说明代付API的设计意图和预期功能,包括/payfor(接收代付请求)、/payfor/query(代付结果查询)、/balance(余额查询)和/solve/payfor/result(手动处理代付结果)等端点。解释代付流程中的关键参数:merchantKey、realname、cardNo、amount和merchantOrderId。描述代付请求的签名验证机制和参数校验逻辑。说明代付结果查询和余额查询的实现方式,以及如何通过SolvePayForResult接口手动修正代付结果。即使功能未启用,也应记录其设计架构和与其他模块(如pay_for服务)的集成方式。", + "parent_id": "80fb1e42-5bd2-4870-8b88-77d31ff5c478", + "order": 2, + "progress_status": "completed", + "dependent_files": "internal/controllers/payfor_controller.go,internal/routers/router.go,internal/service/pay_for/payfor_service.go,internal/models/payfor/payfor_info.go", + "gmt_create": "2025-10-08T20:05:17.6767438+08:00", + "gmt_modified": "2025-10-08T20:14:21.0206729+08:00", + "raw_data": "WikiEncrypted:55P/Wp5RCBekgVSchCI0/7FGaz8xEKK0/uXAbqNq1zF39eqFnNyeeqx4SuTTyjxrkY2RVGC3L0lJkUZ7WH789Y1JfX9nf/LLr7Snb++KDdJUd2zwoEwu9KvRNoPXV2rgj5OPIVd0VZrI9B0xMfEl5+NlyczbNJwz1SIFUX+GOECGQB0mcK0+GwPROqmXYrSBDHXGJOKTfZWWX2gk46tV1xPr1Cz908j9K9ndzSzcTbPnKKZ8cX3dJ+d96NDY3aJk8TZTFxDJX+5Si2n0rk5URpXC9I6NHm5IHuXUsBDrPmkP9EtX6PdLrYCK0vI1UxgadQqysmIgSDJxbDfO3FecJuqdiS/7aqLbuAare46je6Yak20OROHkVjoPseFMOluzDSieu6pbXhX2VtT6ftAxN4vOrGThVyX5Cj1jsIml67WqSmpMQGOUcZ3oHb8cz1/sEDBMd5DgyMIdFNtai9sRhfuY4Psmrk7HmOiA+j40X40lmDigBhp9r8YmwLrIWsWpqArs8p/9LsTDkbmDvioMtLfCB/dZu8qIQYalHW7EtL9mzCGjLXhvRIvYnBKTDU2BisH38K2vI4wMFT+Xkv8MdxW4Oaiq3EXNQ3CsabEiNRMMjuv/gsM1cek6VRxU06et6uACCRUlRAS+np0FrMU2NLihsccYAZGNxdFxr375EKw5Ys7IvuBb84hz5sOxADZzYiUX/GHNALWN0gKVYs3DMu3f05hiARsY3pKDD2UVR/UWJtBStqWzxyOdJZaw26QvYsVnYCzRqkma2Vr8FhVvHtTqjyNaSJjIF/DWcefETovkDA6+sBjeuCRYtyYmzwVyLZVfM2/0PaN6PpNN33u9xWeLz8r3rb9pAkyAtggZcUx1O8d3d/K0XqF11WMWfCvOCaMx0hCnARL0p8L0Bwrpzgz1OFKju7tFWXPAlZnlEOnKumR22dSmL1YHNkytQASM+U4ZjwL71n1gCiwVvgqCLRebFEXKc8EUi970qoraXqwfBjkae/5hsUrJdl8ei9MjAfwKff0QyfzqqnymF8w1QJ3LK/WUnNU65DbtGq3/VdeG1OtaF6KQ2eWaoFe0pn+Qsws08U06i/70zyvVu4nkhYz8XKRRJXVaZ8E9Mid/1/dZ30N1Bj0L2WVkQgF4hbgPt4eoIHFTqBpgcNrcsMCBONiwPe6SyEUBAtMIyqw4i6WhET8NVEpbggE7wWyJ4hs5+NKTFivYQRZqaaoij0Ps2RJdmiQoGYtyE9iCXjJ2KhCqgFZjgozDfvE7xmYE6vSv6/7zaBdc4gtK/jiRLNeVgCstqR7y0PoPZBTKJigaAE8/58Z8qvghVSUQjpftStOkxQBUlVi1CYI1DwtTGwnYUp8fJvHwKV6B1QUAInFOnk4xr/ffYw/RZgiuBK3dSgIBjjXi4Ob1Apy5Rb3t9KAMY5cRgHX0GwM3BoUZphGAaA/mULEKE2UF/wraxLSxpjv3buO0+DQf0YAvac0KXys32NpHHzLJyetldQfNSMmVFOKuA0emk0Av5QwMREdjuJsxrg/AUBxvgfi60RNYMwItYQ==", + "layer_level": 1 + }, + { + "id": "3f59a04d-339e-40c5-8c7f-c98ed6ef6d8b", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "环境变量管理", + "description": "environment-variables", + "prompt": "详细说明环境变量在kami_gateway中的作用和管理方式。基于Dockerfile中的ENV指令,列出所有预设的环境变量:serverName(服务器名称)、gatewayAddr(网关地址)、portalAddr(门户地址)、shopAddr(商城地址)、proxy(代理地址)、proxyName、proxyUrl(代理获取URL)、proxyAuthKey和proxyAuthPwd(代理认证信息)等。解释如何通过docker-compose.yaml的环境覆盖机制或容器运行时参数来覆盖这些默认值,实现不同环境(开发、测试、生产)的灵活配置。结合build.sh构建脚本,说明VERSION环境变量如何影响镜像标签。提供实际用例,如使用环境变量动态配置数据库连接信息或切换不同的代理服务。强调环境变量与app.conf配置文件的优先级关系。", + "parent_id": "53d903ba-6508-45b8-b48b-b3d00d3ed07a", + "order": 2, + "progress_status": "completed", + "dependent_files": "deploy/Dockerfile,deploy/docker-compose.yaml,build.sh", + "gmt_create": "2025-10-08T20:05:30.6861374+08:00", + "gmt_modified": "2025-10-08T20:14:26.0875825+08:00", + "raw_data": "WikiEncrypted:mJFb0eo+82adP8NAeq7d4FgcCqZafL0ho3sap74cjubj7AYi0s/CUFToLVOsgx2FStaMd7X6z1hZ1Y+D0QL0dYsxYCif4mEyT4e1gbSWXJ89J/gHP6akikdtArkgZG7gMlM2b++cB+ycglVtWAHGlPpJ+cDO7e3W5MgOKI2MHzSwbvlflTxuF4BDzfBMu2+IAl1qpXoHcDncWKz01wAdRCv6dyzS4ivnlf6f3Htr6kBXvMzaczRUFoqDFBFQS1XgRQKlKx017CuJEmZi/EA8aIKaViaO9VlIhKvpMYjCNAPhJ1WgGOYgAc/ctAqHZw+VaxasqY4sPkhvHUx3gYbJCnjiIEpQE3+Hvzp8/YVkU36kgADJRa1PQx7TBrlL2DYWWgq2tQCSMrEpbTDWNW+4hY9KN1d3HWGwoU5fj7SmrgpALnIJm1rEeBq1Er4sdCekuAk2oMO3PagQWEnojy+zvmj/mbhnVrAm4jCPxerFfc4BqOX76uUYbYSk0IvrYDjMRASf8dTVnSRjS0Zvwo4+JtQXecrWbuSGSgW9z8lj8GuAX6gm+ht27vPn8z2vZlsWz9MvKX0sEzZx4c6SXxg3Om8j4z7Y2IdPKfZnzJJxRrp1IHzFxnXPgKUPNjlTgIp6T92wP1BoHeSKH+RRpuOzLdo8NCF+gsba3dAVupPSLJyzIpKcgMelpCN62RzvUX4aOhHWwefSSLEzgKXZ12CmJlgappj4sxNm+sVFThxc6NqJqIidxAB8Q9nJ3NiQ+bZHTUqQC0DbfxX0QteYS0tofsKF8BfBtdR/lzsOc6j2ZNq958iBc6eKPhhSjtFNKxgeoSxnpe9sVCRDgfL46m0KqxPwjXygpixpXMaLH97EoS9vMgK1OtmFU5JENUho8UfZrelKRgZwGpci6FCYhyGCjrhUz+7eyo7Up+vLhgvM8sGTuKB9w1PyQQDXfvAs9U7OvWVC3FAmuFnOQFiooyf1W5TuXlaNcbwWFHY/YwTJ9r4u0wWssjtpAPeqc/eJh/nPAQyca/Gw0qygeIFbLW/bBWc+QbDlPA0UA6Cj80u7wCFmLQ7ycNGD7qMDWj/4J4h6Iv28z66LePLtwQbeOwNXljnoOmp9bOUJjefvzUXl8XeGHPvxR/CSclW4S4B1Krg2PL0SYaVrnAkDEYWdpFTH+R8gtBflgR9Rs+bgUi1WkB9nlsYci/XhlJgJgqRI8UadR9MP5d/CGb2WquE/HkSMN5ozZNM0UCzAuwUzTPInrkhWBMUFd3Xv+Hygf9lj4nnJHrG2yX//9IWYaHt1OcqhZzGEQaghBd1CQgwOTNlYxEP5xsBjFE04Lr4qnKnxECnYd0zbFOxA7QFaKX/V51qIt/HrtkW55Ai/jx7UQ7EvvHG6Pnu1SiC+Oat0RtnNAB0N5i/yyMUnHPT9J1/t/LrJf0bVyYzuzKuslBIBSN9maj/facs53NglqRnuR2X0DbPZ", + "layer_level": 1 + }, + { + "id": "8af4b541-5a66-4fb9-86b1-7c95c9f63ab0", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "任务调度架构", + "description": "task-scheduling-architecture", + "prompt": "构建任务调度系统的架构文档,重点解析third_party/pool目录下的订单池与任务队列机制。说明OrderPoolService接口(service.go)如何通过workerPool、eventBus和taskPool实现高并发下的订单处理能力。详细描述NewOrderPoolService初始化过程中的资源配置,包括工作协程池、Redis事件总线和GoPool连接池的配置策略。结合event_handlers.go中的事件处理器注册逻辑,阐明系统如何通过发布-订阅模式响应订单提交、状态变更等事件。分析task.go中任务执行流程与order.go定时任务的协同机制,解释getAllRoadUids等关键方法在路由选择中的作用。文档需包含性能优化建议,如workerCount调优、Redis连接复用和事件广播延迟控制。", + "parent_id": "1ccdc69d-fc3b-4d08-9be6-169095e4a163", + "order": 2, + "progress_status": "completed", + "dependent_files": "internal/service/supplier/third_party/pool/service.go,internal/service/supplier/third_party/pool/task.go,internal/service/supplier/third_party/pool/event_handlers.go,internal/tasks/order.go", + "gmt_create": "2025-10-08T20:05:33.9961378+08:00", + "gmt_modified": "2025-10-08T20:15:38.6055418+08:00", + "raw_data": "WikiEncrypted:sdobwW3Qsckh0ghPExsMqpbA2kkBzWpnGwF1S6hiyzdcrCpDnfd+fJ2ZR1DgJZfvij6wIbt/8sRpS8/oEhtR020FhxyauEwsjcrlpy21Y08jvQoGS6omHTgHFM/rSqu/Y8LU/OGS+gZJHbONfOj31pyTSjQakrCteFrFHCWoC6bW8PZWekrym3ZS4Kd9nOQOsk0+FjNEWFA0D0pXrX7+1eCs5YeWABjCBHRhL1kszsRbho/aGnGhS+C7VgRBubOy26quqpOVSEpBTBU4/wgdkNgS2HOLpOdt5LBzuov8Ti36wMfZlzdLg15uFtVJ4/MbzDECgu98MAkIU3yq6govDb2lMmkCByo/1Lvtkg1G3IWVOvbihTwXtTX6EiJkiHt8xb7eYCxElDRr6XeutTGnbdSdXAzf34adAWgxUiP/LB/Oyzt10tT36MJB4QWy+oHcKuTnrzlsFeCsmT6YpFI70YElDCu5ukTeEXa5kaWn+yS6TKIbl+keZRqZR6EWXX6VrCL3+RqxKvIt+VeuXrEnP480vh2KP6DLNJBXYAM0WOpJJl+xUVYEIzEy3R3o/2xvLNJSGTRvDbIdcarJWyDqZb3MXfUpZb389nDv9iHB6gWqBROb0Yml5cnRqx595YxExE/IbvreTVy7PH3eSfxKadHw5vm6+2GLZDGVm+LLbbPHH8HmIbQxD9TkGaL9lqazVck3pJeD/N9yFd1HCaRlGKSBJPDSfagiSwZ6zNJIgQfWJm/AjyB2q31340x/+0mKzsSDiDmAGrg7rzpkDAx4eMwktakESZvHild7u9P4nMkCsN348uofQIrfbPM14lmRFbva+6rn5KAEPpdWmzviR5HBZQ7jsK4G9E0fuesJt6HBZ0WrwVhHLIiTkwVNtwNi7cviRUYHOPGTQ3z9V674FE1aQ3U4eXOegvRbjxQz5IZZAHvvL5Ph2kgZD4/T6TJUBVj88Qh+bt3yiJCEyf9KwLhWUEZpqH76FrhBCdoR00dJc0Y6JUYvBwlDzVa34yGL3yx/dS6GhmljqmAZ9Zspk9ZWcuXRVXJo43FSg8agKpwbwkgiI2ppS6p8oogEfNdWFV87W+KdF7azQejSXNuG5IdyAhdjbjtFoPithQtOtLHmFOYiMY1Jlp2B8q+JVx2QbN4hs4qNRvZIzTHu8anG+4F7A0IIaITL6OR9zgXBqhHc9kHOZtJRNOXTK1d3hTPDFsWQE2plCAtskNWD4Fc7186I69IF7FGZZWm2kpq10wsvFUtQulMaDx7Zaw9O67Qljg1TRRIB1U6wkdCg03KXT35W5mIPB9o0WJeikaqQf0H8kbkU/ZymVQQZhkJw3op/uRwuDsSItIF6EIUDcrhwI73+RXrGWEcuhG3/VzR3pDV3QI5MfAi+egm+sJWhrV2QcghzOugO8m8W/Knh1PyNRljiWIOlHQJP1HpuaA8XbOojXyFGm6ed3DJodR0T+VmgUPArDh3O6zTAvCclUSOKY9vljdEAj5NB1RgynhH9H6wDRp398yRRt7AAD2IEtsNShEHmPOAOVjbQfnSqO1DbUhQ+9iBmEVScHy4fZO7OQqzkRBnhXPsvgbfI1YKWP6NNp26IkPR46HS89WUDlQE1h+JT31Opb2v6oLu83pRmcIVLHmPWLA3n6jfjjiF8jZI5LGN5gcywxUXAjxwMgl5TTNrWRU5cOwLgqTbBylWl7urnO1Sg6UzI9VfRhlnjA0O/", + "layer_level": 1 + }, + { + "id": "40a4568f-d8f6-46e2-a301-107062e68778", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "Span生命周期管理", + "description": "opentelemetry-tracing-span-management", + "prompt": "全面解析 kami_gateway 中 Span 的创建、关联与管理机制。详细说明 Span() 辅助函数如何封装 otel.Tracer().Start(),并自动注入 tracer.name 和 span.kind 等通用属性,简化开发者使用。深入探讨 CreateLinkContext() 和 CreateAsyncContext() 的设计意图:它们如何创建与父 Span 关联但生命周期独立的新上下文,避免父请求取消导致后台异步任务中断。解释 CreateTraceableContext() 如何在保持追踪链路的同时传递完整的 trace 和 span 信息。阐述 SetSpanError() 和 SetSpanSuccess() 如何标准化错误和成功状态的标记,以及 AddSpanAttributes() 如何便捷地为 Span 添加自定义属性。结合业务代码中的实际调用,展示这些函数在订单处理、渠道调用等场景中的应用模式。", + "parent_id": "fd2a2cba-0887-44b8-93c2-9cc9e520daae", + "order": 2, + "progress_status": "completed", + "dependent_files": "internal/otelTrace/span.go", + "gmt_create": "2025-10-08T20:05:46.2714253+08:00", + "gmt_modified": "2025-10-08T20:17:08.4080837+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoBD92U64q//WUZekSRqHD5dHvMGCTFBVAVmAVyDQD5vhdwOgo0VUMU8J61yU6Nmdlhjw45DnRWLgYcJJ0fcNbzBX0d8MVmktcot6LmM0W67w62771R3jGtJ7Pk50+pmBCIGvVPnk5FTOZMk9+pmyKUkMa0aNveHpnFJClY7+3aE2GIA10mgDmYc7XoXD+vJGYoizJS4xN5g63oAReXr4T51jUJkqn1bSheDlL6tFa1j8kWB/39b9gp9JnpDFsrb0Kzq8UjbdhCeCS1cf5Rln3Xr0WMZ40LqaUECj1bB2W0i9ot6xVnls8EiZRkbsVnk622PYv4Q9FXB0svDBv1qIjKWx0BnwrtaT1ldfbJMM6lRANdOTsxpEs9BhO/OquI/MPyR2pHjAexE3IKGnM0KzxbGiQFjmvc9lipK01/nZpUFtXT6ZXJKF9tYSbalC1zlOZik0ZyeOpZRPVnkC5cfi5FjMB7CWZ/W95nbwFrhMIfKw254n/QuqMRu5MvaDBo5WK40+egL0EVmtXcvCdds3DbrItGEyiCraFLfcPQZbNnU43aYhUYFjUTTI3OhqVSoknsPBRMpAgd42JVHNQuVIxkNDS/nhKVi5IYTVhZQPH+9Op85Q7CkMizwb79v7JRV2ejqqccPI4iAotfsgN51tQ5wBhU4lE/Aca/GE1CJvZRQjmHOQfm1US8FDuPvPGg2qCl8HW1xM/UtxaTm39FZUjTWHoTFoqhTA3CbbFa5oZNi4cMcQM7ALoBq7a73JsqN8Yc7l20vrlZKPKC5dm30foWyJJpByQXOWDiyEbshHZabW9EvvMNHnG4eZr7MZ+z1pj86wSA/k+Jjx1rBIQCYmMUnvx+jn6aa9AKPmd0CG/ZUw4ucCDZ9l8rB5xrLWPAkxh59O18rWJa8lmkylDgps3G4Ui/JeGHNc/OOs5a1CUhrJsh2ZhvjXY9cu5gl+kbLfX5e1Gr0mZ30DSJv2ZnyI//aOMyCxJvl+0EP9yJK8tlrguiR9jzHld2eRahxya+rthkFlPdVPcG7A+fMBO1b5Xm+Ntzpbk9vC6tH4/S5wpHBEcStLfpJmeK49yZx/izEKR2IzGyxrO8M0pHHWKjiSgJ5o3FjDSzL8BFeDNd9k8Em51aoGTAi1zL0l+12m6u+u6vDXx26YhZ5v7dgyFOadwqHy7RR7A50O04h6nKZ6XuEDOTUOiMzu/MVGA29mAvBl6QveU+CAo896s+kfwI+0nV5R2/AQ+SkrylFfy5pYuIyZN4lS+8vHJQWqfc/YtaPuBBJGctvJPEGRqiBFAT1JNBIDTb2avxhd5VZFXLmcMTBJcXkSabvUmLHoQe5goDO5eQW4Icx3MpXmzplMCDDIernOixGYTEaGFL+7Sm9Ndlr8/yWHLpLQU5mNTPFUU6+xziQ2Zs8yJKGZFm76xo+p4FpMUCAFWGLbX7WcKpZ/SJacGkGEaENn3BgYTaEudLLDgxRon/9M/3eala0k4mo2vzX5TJKq6PBcvl7X3Bh1Wn5VQ==", + "layer_level": 2 + }, + { + "id": "1fedbb41-1015-4ec4-aaa3-c732e30b12f6", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "采样策略与批量处理", + "description": "opentelemetry-tracing-sampling", + "prompt": "详细说明 kami_gateway 中 OpenTelemetry 的采样策略与批量处理机制。解析 traceIDRatioBased 采样器如何基于比率(DefaultSamplingRatio)控制生成的追踪数据量,平衡监控精度与系统性能开销。深入探讨 sdktrace.NewBatchSpanProcessor 的配置参数:BatchTimeout(5秒)如何控制批量发送频率,MaxExportBatchSize(512条)和 MaxQueueSize(2048条)如何优化内存使用与吞吐量,以及 ExportTimeout(5秒)如何防止导出阻塞。结合生产环境需求,分析这些参数对高并发支付场景下的性能影响,并提供调优建议。", + "parent_id": "0ebb9117-99a5-4092-862c-49ee70ccfee0", + "order": 2, + "progress_status": "completed", + "dependent_files": "internal/otelTrace/init.go", + "gmt_create": "2025-10-08T20:06:11.5781251+08:00", + "gmt_modified": "2025-10-08T20:18:01.3430547+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoDsIAIxUszffcg1n4BKyPc0aCrh3XHDd3xQPINQN1cnKs2UlshAVLYNB682wpS9K+rHiDRtzevtJr0BIvXNsCzvE3m1W2V43gL3oyS9J3BkU2aQ3MJJKQrM6fOHFLiZQRbYn+xzJ9SYt+tuST4mw4rVleLisFHpZcZqsynjdKt0O6Gr9ESyApUIqn8iJZyS4gosMMUWYc09/QrsPa1tJ5qyOLJKkjNwAPU0ahg1NJRGfRwx2+RWGkir38p3DN2ZwC7ZRexa5+I73sK8+v1dgxhig1OUAuEF1GG+EI2w8YWE/sqXZiiuUTZ6bCNomJqsq8rlW4hffLJ2aVusYV5barBxiR4X9vAbdYRwWLAiAAGfi0Sh4Rbg/W/usKTxvBXDmApYmvcTcwyEL/KQUbrAig/tW2A7CJ2Uy8DQGpZfNpQMB1c8WgCwj1wIdhpeH0EmoV3Xtu/l22oixvdyXvnwei3LTH+wmEBuXjnZ8ehvitF+7GxIO0j5+wwZLZcoluOkK+iB8GTCWCqxNl0/BQM2OMqa/dQT4e6xpp222d/qGIsryqpN/7niIHQVZCFjOqaX3nU0dBXPfyBqQWAGBEj7HHwHbXYAFrV9PFT0GmlVyhAM+tL+jzCJCoXdJgvB+vvTmdD8zdAPzCOcct/IG68qtQHBv4WHhL5beEmYp5OJP18aMFey1Ei7fCDq/LwJksRIFrDzwNPrIpdQDbePyC+O2g/mPcg61p2WnFpAg1hR2t7dNj5CJsDpwL37t26wPgmDOpVci2WrE1iMSLdNekLrktgl+U3ce0SLl+cxq4Zkvyn+8MDaXErU0yORZygxHhWa0oKu2HJlMRVlEA+1QZMW4RxbKPVndCeTYnVppfDfb5TL1ex1CrqpM0JS5v4Fg139fomcnlqK/XlGIACiszGcbUQ6OmQUffmqaaujG25u7OiehvEtHQWkxIiVbhtl1tSKxBKzh+91mZuVzJJcLaqd6z1JNRzohAXBfJMJTZkYCe4heWXu4Pbe/RMiTMiDy8e95rbJM+DI6oPH4i0bW2+GPQkr/q5JqaOi0ey4EtPAL3oqugpC0Rq7DiNTZep8wTDjorYWJxwss1ZiRumt7Vub1rBlZdAJM/KUukLu8+zFw+5OYT9HmNfXDV6YnO1ucbl8SkE7Qs+FDFETAefqRJZXJf5lj2VR39iwL2J7fPiJsAaHFQ==", + "layer_level": 3 + }, + { + "id": "a5d56738-c20f-4178-9f81-d01bb592f194", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "数据模型", + "description": "data-model", + "prompt": "创建全面的数据模型文档,聚焦于核心实体:订单、商户和账户。详细描述order_info.go中的订单信息模型,包括字段定义、数据类型、主键、索引和与其他模型(如order_profit_info, order_settle_info)的关系。解释merchant_info.go中商户信息的结构及其与merchant_load_info的关联。分析account.go中账户模型的设计,以及它如何与agent_profit.go中的代理商利润信息联动。为每个核心模型提供ER图描述,阐明实体间的一对一、一对多关系。文档应说明数据生命周期,例如订单状态的流转(从创建到完成或失败),以及相关的业务规则。同时,涵盖数据库访问模式,如通过Beego ORM进行CRUD操作的示例,并讨论查询性能优化策略。", + "order": 3, + "progress_status": "completed", + "dependent_files": "internal/models/order/order_info.go,internal/models/merchant/merchant_info.go,internal/models/accounts/account.go", + "gmt_create": "2025-10-08T20:04:49.3979036+08:00", + "gmt_modified": "2025-10-08T20:08:34.0332817+08:00", + "raw_data": "WikiEncrypted:klcgW2PbPxJambbKMzvFtzKMOkAiMygw2jhMWheBgWjabVsg22USnmOBp3LIxuc8I5oEhmwc+cjSueyWYZre1tSOmU2DILRaLVS5z1GxT7b1+PljaBuORTcFJrCXeM0YQUrxF320YEotDDoSIIXzU87xA2wBqxAusH7/M4pu5NE0Kjh5aqW4fRuzwkdVKeMJ1hsZSGjUfZLP+HC1eTq2r+PbUUWpkE1T/tGgfx+BKCkMhfLbDe5VGWmQDOzOs42wFmiLBRs5/SiaMKe0HWzyWznuJuzJGGv3S/BOSY/FP4h5GPntRivq/nE3O0FKvUd/BUZpW6GmovZNQXLPGN6XWI3KTYrWP8LHa/iqQH06DhcO2jkSTR/6bhmyzWyJs5zJaPQSwq59KLCs6wok14vMYLeP8/4BDk6vtxU0YthjgSwxxdUfOW8/uOQjdBKp19JYPVzGmKlx0JsOQXDQsAsTmAI1RygpQRsC2uAEPNn/u/omTh64g+YfyxtwlfAz/txZb6vAMzEMlE0J7fToHPwp8LPtI5ghix/5g/Z3mIU8Xj80crQP1+lOv2AynXCZ/ikGjNJzvYk/2YTN0i4ISrpdgmOTNaZF9SGYHy5G5pGs4dqnGBELaAcACrJMb16OSWEID8KLOFuhjyTVobCgVVCC9OA5v7Okdz+k66sK5lqa2vAp80EzJ/2Bt5H+8HpTc7IuKyBIqU9huAZZsX778VnoN7F6LJvjaC9rvEXHnBRP6mUsJKa8PO6TzQUu8iAyxcJ6+vQ9pHp+3X6/ANsomu/S2qBd5tlfEU9UguJoh3ZkjQj8+DYgSkyZ1zzV60vt4Iz4xZOMbQ+pupoCFkkQUjztpgqoPjgoTHgJfRfO4Sg9jkBwT1+ajbPZmTVE8JbK3GVyIol5iu9GHNSfqn0A+lZHPeuJ2dfW9y8CkeU3HU1GVjjvNrco4x+GZ0x1lZVcq3cSwvU0POo4N9DjIS9xnXL/3/4DKCtg8Fjlj4LHu7IJ6rtn/z/SSNtPkOBtmI6Ha44dRkK4q+ayPJpu5z9UubmM70Wj3BSYkM8GoZGIElSSoHbZhdN1S+67lZBBIruSBJliVujnXsp2oyMsTqLT08S3mKR/D29MmMLUEiShH58gLE1utVZeXIEELNMuZSmW8I1FEXbnGMc/P5TcaRXVV2b3eRJVb8ZIJCHjy+zl4YmYloCPk/k1xuVeazqFcl/BsvqVoWpFYPKyRZTlhVBKcs7g/qiUhfbVtwYItmuEF4b/KArPf4pvk3bUMMCkZQAc5HKQqpHQ/d28lbOqw/gVY6PoFBjYYiWvhVsnieEL6vfx8+gyZsjkI6Te0GFotK1rmCK7Auw15cKUFZpIu7uH7F7EgfVJ7D0T0ulM26/Q926NFle49aOtTlzvVuyGJ3W3EbLY3qjGls//F4Lg2cRIjfS8FRJa27ptWIhhCV9RtryoSJ4pNY/NzE8ZgupxaH/cq6FprwU8rKV90QobEWis3fnKscQj5V+UsJlybWtyOtTBsOjb3566lKUugD7eFBsYYYJW0cSgPZW6Cleopd5Bv7D3+dDuqjd6DyMSfiR1wYCRXdM=" + }, + { + "id": "c0f73068-9c54-4cc7-ae03-811f69af12c9", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "消息队列与异步处理", + "description": "message-queue", + "prompt": "详细描述 RabbitMQ 在 kami_gateway 中的异步任务处理机制。说明通过 github.com/go-stomp/stomp/v3 客户端实现的消息消费者(如 CreateOrderNotifyConsumer 和 CreateSupplierOrderQueryCuConsumer)的启动流程与消息监听模式。解析订单通知(notify_info.go)、渠道查询结果等事件如何通过消息队列解耦核心支付流程。介绍队列管理器(queue/manager.go)、任务处理器(handlers.go)和工作协程(worker.go)的协作机制。涵盖连接管理、消息确认、重试策略、死信队列配置及消费性能调优等关键主题。", + "parent_id": "576b2803-bcc0-4769-89b3-54c89e6b7381", + "order": 3, + "progress_status": "completed", + "dependent_files": "main.go,internal/service/notify/order_notify.go,internal/service/supplier/third_party/queue/queue.go,go.mod", + "gmt_create": "2025-10-08T20:05:11.086892+08:00", + "gmt_modified": "2025-10-08T20:15:18.9609185+08:00", + "raw_data": "WikiEncrypted:IaaHBhg4aKVK2Z27STIpf/b/nFD+cBUnNsF5DeWv7A1urYlY0Tcn/dsclaHDhOF+ypTw/p74KK09fCSdGKQVA07NZvyJSNTYCKMHrKMBxC8GnxZ3dSOG/TQ9IBFxIPZ8165juzSJk+IBVODxNOzPoRI2mOkEzK0skIEWx/vMOLGHvYUb7mSXrxhiW4V4NaeglYPEp61lKJa3Uq/yjtivEL4Geaohr68c+TR5HvSkXeMaVauxboAAegTCM00TPbIKJ2lobxB7UaIenxkapur7o6Y3slxnysSEZeqlFbECpC3bx5qX7eiB6qZHnLaXZmAMZGbA8SLBpy04eGEKRgCPDvtrKOuSYEhpVtEPR/rfJIdCA9WV6F5plCvaly8+lVSw9N+NhpbDrGomRAEDRbV58txXhiy1jGa1c7SBvsyAtTOgp/fTk/m+pAbef1W3ayqtKTe6efDZ1Yw3DDe5LAUWbTnxXSLsWJgAnNozCBzMd2yMuPnhdVF93oTQ4Aw0W8Aw5PXskIctyfBcR0IQHiccS8kzXLMnNAt/oGnJFytXmye7qc2MWe1GW+zH8bCrOazhITJaMINfpgBINeJ/Z8tmnPn0o8rOFhT+vgnWVXNP89RTC5rjuqGhn3Ud76ACgmCZWhgW6QSiVZGf9J4KMXCFw/G3LKWyjG1mef/SSsI332L+rAzupSEA5EGPpb5EoqrmJbkUfNS7+tDgroa5j4+QigCeKrkE5O1VhDr0izKrc3umDp26e42UKSffOK8Pt2iOuf1fMhJHDexi10S0KMMqzhAav1m3b4pOWCWaWwEUCu4v4sEqRinCL+kK2o7IEwCe1zp5VRD31cYZ3aTlqN9WMMSUPaLksYNDMtSG3AicBZH2qBWEXypVzoRgOkxrbq/m7nNIoFj8ScGN7xt8M2JOL2yxKAzSFa6/ZMi7HHDzgvI3PErLYS9qXjmc7O4HKnJ/i4JqtL8p3qNzGMokXdPpbk/upLxntRvZ39JxZgmHo0SXYVEr4YsEfP3HO+vzGYujMj6FTJDT8DpA40KRmtSuo2dkiAKxevJDl/P46mmx2lNKRn7uZUiTvJbn0RoOzuLQ7lPVD8BjW2wK7B1upzv6iNXLWM/w5PleEel7IaoY8Wi/uOKPzhNxim+RmRfh3hSU12VZc8vKXWnwFlC1vqWFcTOnDGkE6gznOtxWEDVq9nsxXUezQdtpfxCPwlzbXyib5Y1wquy4ZoQ1m/ICUZzdYKGzRo8YrSHnZn4Frp313OfoI6DXVAjrf2BY5kBdRSDxnHQDpi+s/T80+clR+h+7z/L+aCi34C+UO1wS2y3HYA4=", + "layer_level": 1 + }, + { + "id": "15483189-42f7-4bbe-89bd-55f035c33ccf", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "回调API", + "description": "callback-api", + "prompt": "创建kami_gateway回调API的全面文档,覆盖所有第三方支付渠道的notify端点,如/mfcard/notifyV2、/appleCard/notify、/tMallGame/notify等。解释这些回调接口如何接收来自不同支付渠道(爱博、京东卡、天猫游戏等)的支付结果通知,并通过对应的Impl结构体(如MFCardV2Impl、AppleCardImpl、TMAllGameImpl)处理。详细说明回调数据的处理流程:从接收通知、验证数据完整性到更新订单状态(通过SolvePaySuccess或SolvePayFail)。描述不同渠道回调接口的统一处理模式和可能的差异。提供典型的回调请求示例,说明如何解析回调数据并将其映射到系统内部订单。同时记录错误处理和重试机制,确保支付结果的最终一致性。", + "parent_id": "80fb1e42-5bd2-4870-8b88-77d31ff5c478", + "order": 3, + "progress_status": "completed", + "dependent_files": "internal/routers/router.go,internal/service/supplier/third_party/aibo.go,internal/service/supplier/third_party/jd.go,internal/service/supplier/third_party/t_mall_game.go", + "gmt_create": "2025-10-08T20:05:17.6849003+08:00", + "gmt_modified": "2025-10-08T20:15:38.8092672+08:00", + "raw_data": "WikiEncrypted:ICiVViANlur9hTgF3KdhPBHe7iyNKaUrLIg0l7sLo7hTKd8xk03MceVQ2xU4zmVOKSnSmvPv/qHWmU8lu5XU9Ag1D29u+6w37saFWSFEINiNkFNfqI1ZUmqFOt8LT2OIehnvWEPfUqtdV36ObR6f1OqA1SnMck4nQyQRL0H4HnYgzDNofwi6rWFmwjgP725JI1YYarnngI7LWf3yYPYmDXtGvGUq85ArOascFxh76yz20xy+/WkHDpRquNk9kn5Y0u7H2qhCstQDHgGqMLoHy8fShb14Ikk6V+s3+6y2YIZpxn7ctIMk3OedQ9V3d4JUQLZzIpNgumEx+npS6lGMjjolfSPcNL4SCt8SJBIiiHHD/zuOyjlXEzxJ3NFMLwaLrLRB4AJBnXz0MOlS8b05sYQZ5EFRPnP2xHmUSrSpgC6PCXbL5bv1Q0tDcRc8bX94fKr7j5gvj5hHXUBu8L2V1rmRcegHfxXC/Lu8HMmGFsPpobtZmIozQ/jOoXle+8yDLSlDYEocIZ+zOm9kRwpjeRxVaZmcCujr/4Tcm+qZNq42HADeSFxWE2kRfT32LygmgwRIVhUg/zU/EJSgEA6U64hdRIWJ9j9NMfUUkIkRBCM3yz6WdV699gO63DiSKnaJC8kLe4UAsvrXsnIgPchK53NXgID0i6OtHhErrkBATefef8z1wU3hE6TrEwvYDXcCmHeb3p5t7EHHK8UARvsDNpdIz5F+L3Tgh5yLb0PhEQBWAXVSUod/httvdO2tUkoHxY8qr3kLEmTzh1ogL0+MOX6lY0L8yTIYXtZqVHUqKjT4S4Z4/ap9D3W1fsbarkKD6fviUmr8EyLO/b5Zu1csDmx7z1UU2oh2e/FqZRq9mD5yF/4d93d0bCCTMLo56AodO3DMFgU1aaAN0ytN2WGtNGhbaw3WD780dB7DkzG8PJcVlA4eLj7q26wBpYN1Z2XD5eKGeb/yLjEe9dYeJwdvUZHagQeFn9Lwm2Apnq085MKk1nE9jtZmjVumQLJYjBjqcuj6tmYdMQysh7hdNBevFcSLfuGbTB9eNhqANdyQwBpTdXRHQMEZtjBttuxc+2G3uvlSdWeDiYZ9wWdy/QUHleMow9kqTpqi0ThLFw63xet87yoFIYdQSRGETRT0JtfZDjR9qHwrdksCY9BAoWuwSObK1y05fDL+WmqIXZUS4I2ZN51/hohNxxOURxZPcB9JRoAqxWJbM+fLWipiKZN+UlzfahzmVHngEpNeC93mrqHBG1d+xrtz2CRlMTuHA0Bq/S6crtAKsND+H5qU4dq90q3eIW/TBnIpLmeMNdxZy6iAjX34yrTKHKYWWMDraH9O7PWqQwTYDSSVkpr828tfKXov9t7ZVnMFyaB9CnfTLIff0AfkuY0DkIQy1HdQJDy1jQCBVZUw82sbm43KJaR6zEwRebr/hGynHAy9kq32f8hxJzG3bpoYwgjQ/UFMyhN1mwMaFaBxQxkatMnWDeXCIEE8VQ1x/dak4Wcsz95enKk0za+xPwo8pja+D3+PN/pAPqvAH+pnmgThsC5fbKUZj2NHB2YUcydT6cIipV9sstE/gzDlT3ExTQIRxzn7LvgF", + "layer_level": 1 + }, + { + "id": "556f07d5-845b-4291-9b39-b0872940a3a8", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "日志与追踪上下文关联", + "description": "opentelemetry-tracing-logging-integration", + "prompt": "阐述 kami_gateway 如何实现日志与分布式追踪的深度集成。详细解释 CustomLogger 结构体的设计,特别是 WithContext() 方法如何从传入的 context.Context 中提取有效的 Span,并将上下文信息(ctx)作为字段注入到 zap 日志中。说明当 context 为空或 Span 无效时的降级处理逻辑,确保日志系统稳定运行。描述在 init.go 中如何通过 otelzap.NewCore 将日志导出到 OTLP,同时保留控制台输出用于本地调试。分析这种集成方式如何实现日志与 Trace ID 的关联,便于在分布式系统中进行问题排查。提供在业务代码中正确使用 otelTrace.Logger.WithContext(ctx) 的最佳实践示例。", + "parent_id": "fd2a2cba-0887-44b8-93c2-9cc9e520daae", + "order": 3, + "progress_status": "completed", + "dependent_files": "internal/otelTrace/logs.go,internal/otelTrace/init.go", + "gmt_create": "2025-10-08T20:05:46.2778114+08:00", + "gmt_modified": "2025-10-08T20:17:17.8120722+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoDv2B1PcPRFDVcz8A+RwiOsJW/7A5d+8LUae24axAjLEBQ3+V/sXNwuTc7IvXUHHqgzMr9Nq267ZnkYahh0fj7NG7aPLtzS3Czx9g3QF+RMpSTDNk8zrIpaVYv18/yV675MJ2e1bGQCul4v5E9yrhfFssJSwDNy0y0uvj+7KkOjZcal2LdA5sboMa4yWvcIGA0ytjkFw0iq62rnOT8oq4PnXQ589aXJVV+FuQyy3yz2YKVaRgFiPEN2g5dg3HOcGmE/BAW0AQ62aHhEoJBDwEzAjDCoKGQ9jtNaCvHNgrs0tnSqsnFPoyZNzd52qW3LUOG9nGVJkeNgh7xD12znvIJh7ftRW61ARygxqTYg3ti1baiViFQi+3KQfdM5lvYstgJPYvh4iZybu/2JcEvleSMzHqjyhxOY5+GlWUPsIz+aWFrQXDAI9+GeP3mFlhQynSZ1ETLv88zawMZudWgmLehMfuXlPbndtFhjT0ZIlS1h4nRov/VqUhMEZc6Kecwc04s/GRy0HtvSMcC+CzJIrgR1LitCiSZ6XKhoNz4ZcPOySFs6iWygM778Adhba4Pdf1bib1r4whiJIGc4E7lFWdyrlM0X7OauC1ZDIpq6jn9aux02AhH1dWiFeLI10owVB8oAjkMANHfgNzXE9DFIho/+gJOOoIyWEgrWbyrdeeQm8+9hNa3BKM1jRQoM9uGX6Fbcnjw9F2nDezhAVTPLEGbkVc+I7QRBfaVWuclXqVDJJy6aeF8UhCv0w3mfZEYiWdn4jtVw7LOEajzvQgev3dnzwKZghGuwclbr0mk5i7Un7UNFaFnAsBTrebYJv7cwDceWMvq+daB2w0BzNXhjtvue87qz5EVW3m7/V3f4H4RIyQ0kb89l+ewVR1hBzhNVRzrj/+sZvgswrjaOxX6Whj3tLZutu/wSnRPVMY9xfu3R1wRh9/ASMKc9EhN0gNljKwLiAOPrdnXOwwEl/SJoCHG148KFrDtaFMeN1P38SOqMNmwCGYl9IKgsgXkXd43la80HvCA4geB/KsXxin6cj1tde3wLYeG+pqn6B9rjaiPDMkvxrFSc5zi9jrNRcuElWQx+CAlUTvVKW2vOsPQgkg1dDomHuXgP8b3GrRwg9uiuItmrohjWLzOx8UslVn1i0xqXy8C1LKTLhSRwxNgO4MH6i6UKOADe20LsCTbG4kIpngjLWXCCgQI7FLkqqT9VjoXWvFPVOKAQxcyxKlx7KvtK3CbdH8AyUmITJPbyDvk4kuX0fn5f3tktYi7Ooj9xw1L/1p+TURXoAmMXsNSPnmxcfLaHhC7AvmaDhS1YwEbfuvJOYqwwhpr1TlRA+z75wREEA22RHsAUzGd9ld8WsWwb6y7R+CeWVNK3Srq7rkPMyTpDA00UpQHJBvv8FPmhdkg=", + "layer_level": 2 + }, + { + "id": "25edcf0d-932e-4a7e-ac78-00f9888b6ac7", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "分布式上下文传播", + "description": "opentelemetry-tracing-propagation", + "prompt": "系统阐述 kami_gateway 中分布式追踪上下文的传播机制。重点解析 otel.SetTextMapPropagator 如何配置 propagation.NewCompositeTextMapPropagator,集成 W3C Trace Context(propagation.TraceContext{})和 Baggage(propagation.Baggage{})两种标准。说明 Trace Context 如何在 HTTP 请求头中传递 traceparent 和 tracestate 以维持调用链连续性,而 Baggage 如何携带业务上下文数据跨服务传递。结合支付网关多通道调用的实际场景,举例说明上下文传播在订单调度、代付处理等跨组件调用中的关键作用,确保全链路追踪的完整性。", + "parent_id": "0ebb9117-99a5-4092-862c-49ee70ccfee0", + "order": 3, + "progress_status": "completed", + "dependent_files": "internal/otelTrace/init.go", + "gmt_create": "2025-10-08T20:06:11.5849914+08:00", + "gmt_modified": "2025-10-08T20:18:48.5953037+08:00", + "raw_data": "WikiEncrypted:33j0HG+E36k1j4TTABG/zRQUM31x/GHt6fXcMgIHzoAYuIRNEi8iwu4QgZIIA/MkCXvu5RTXNTW8eELtw3O6g/VgWhwiurL+xFX/9XFMKWDQtfh304VWlHBQcnezPDJmRFygD/K5AVa6CA35UWSkpsMWmpZ/MmvQUqQC0VHsqMkGf7yv9XVMyAHjKzWoXtk1D4rAu0Ie1VbWfLmaMUmVA+e7GqxfWGy6RbmxGX7L9dDxcD9TbpmHYVPOUGtMht1zmsnHZ0N/I2a7kXmwSLzKnFMhK64uSg3Em62MXxfZGpH494ysLsb5MnX+FzBxCO7sakeMZ5acOEX5NdszzPleBbAAPUA+tJx1ftuG8URgzUKNz2yW2ycno+/y1PK2uDuuNvAOmIjxDJj3ypBhFQKNsexm+3pQznc8NgILfVOkGt4QrhH5NAduKR+Nd68WYwaV/MxHqGuCX5uV47g/NtW9epeAXL8dn/EOP7iar0AfVUm4QGy9g4ujXqf4ib7blzh4ANqDRjfFblFEhxvOi1MqRWqyz9HEUjdK6N8/VwkMNuU9IZtl01saJKIUDWzRREfm7c8wln5kyTLR+W0mtSWVep8TXxAxRqKD/R8pq8F+u2T+c4gM34PRFx8IGWvDlXUf0D3sXuUCWMz4gbJ2ckhK1v9MFVIuVKXZyB1g8Uk9YPjQqJkyhHoDp8nILQSP9kBWl02qMsN39EYDQAcujtGIe9YnEVK5b0gXsOTp8/x0kLnLrB6tMzp19l+FEKmVntQ5JwtTeMRpQmnR2gMRpZmroyPq0Q4kbnMz1pQCCg0WsvFukZrg4x3EBFJxwN+PcI8/Ic8WuMoNUd0Oj8DZdX3aBIp0oYX1LDZr20DkvSyO95JbJ+QJMaHYKzuPms1VbSZ0HCEnXEdtBY9cs0R7Mz1dcUqNwN6XTraftau/31McVaSLO/0NtU1+HAfPxPDVADdsO7K/OofkwMmLgG2R3gd9yEHC7i/tRRQZ+lxQg85jindlzIfNkYiY3VqjJEk78roiPg5YVZvXX7l67mruozacjx6mf5g5Z4NMnIDZG4VT5R1UJLlUqazg0i1eaVboLNkfrCAXBBSSxfa8ldUEhTzQyJRO6pvQU0mUpGo7yXUuwwbmHiC31WrqjjUr5XneEshDUI9/Ey+M1R7nzFljePzHnTiKFFz0V1NInkD4IGbvdfl8MwaZt404rpcBkqeX07Kh", + "layer_level": 3 + }, + { + "id": "1ccdc69d-fc3b-4d08-9be6-169095e4a163", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "核心架构", + "description": "core-architecture", + "prompt": "创建核心业务逻辑层的架构文档。深入分析支付服务(pay_service.go)和支付解决方案(pay_solve.go)的实现,解释它们如何协同工作来处理支付请求。详细描述供应商接口(supplier_interface.go)的设计模式,这是一个关键的扩展点,允许系统集成多种第三方支付渠道(如Apple、京东卡、沃尔玛)。说明系统如何通过实现此接口来添加新的支付供应商。文档应涵盖订单池(order pool)和任务队列(queue)的处理机制,解释third_party包中的具体供应商实现(如aibo.go, jd.go)是如何被调用的。提供一个序列图来展示从接收到支付请求到调用特定供应商API的完整流程。讨论架构中的关键决策,如为何采用接口驱动的设计,以及这种设计带来的可维护性和可扩展性优势。", + "order": 4, + "progress_status": "completed", + "dependent_files": "internal/service/pay_service.go,internal/service/pay_solve.go,internal/service/supplier/supplier_interface.go", + "gmt_create": "2025-10-08T20:04:49.4046792+08:00", + "gmt_modified": "2025-10-08T20:08:12.4576473+08:00", + "raw_data": "WikiEncrypted:4PoKJZEjoeT4XL3d+2H6W/6FWVAUV2gnu3I7xl7Vy/iEOxLqpYxB7lCXCUAq+rosTPdhYzRKNIQy4WAdufTOJPO98t1dfZrbfMRR56Banyj9JeWRRO5E29w0EUaC/jEhvGTB+WX7G50HIUdvuld7JhV6eehwvvln1bgBJR3eVUmNHtTD/p8JCfzVsGTtvmA3Gt7Fs2rMU9TKcpUaQBr4xSXIu0o3e4taNjBTU2Rx8YjIeDGIqgiDtTdtcoy9NikVSpCrsptusj+NStyh6DvDzhCiwEKf2HVOKJiPV36ItyjSlLs0cZkZ3Yr0AiMTzIVjqH2G2VfUgPsBmug/vDSnmaX3Ha1SoWlmZY2LESG15Qw6I41sEg7Ke/XODasjyjGl3357gXYhAssu1VBRVVx4kYJ0xXD/bGoshTJcZYqMGgYHM2f0qOdqC6ybrPYmocf1n92fncYBfejKTJ/efbeZQ/D+gRXrji3ixjKa5mvgggFKGVTzzBbKRy7y9iqfzQJaP2IpetXn7Lf8DxBiJ1xdrCowvSHWkGBvRSBx9ytZu4BhJareqjJiufFAV89uyp4Y5kXujTukn/MGjO1Gcu5/aQPxAjPuVdCtfxQeeiReFyOZtoc6EXbms2YFu7mRJ6DThgaoAKAFN0+rqHDYdKr2Agkej5OGEyWQrl+55Euca0VjxG1k7tQe1q1z/2ekLNEFdFR3JaaUK9eM9zAjljgG2d3RsLaLKFudauf+6IKat654mCixtWkG51ka7jH5moM8iqNxlwCBxhc+sq4lhlEDGKRoDMwizJvN5FFvUr9Vzt9sPoe7ch5o7ViWRbKkdqrLj9cUlXPsh8B970WxBMsU/b3kMts30i5eaPyrHLfx5J/3YIEn0kpD4IuOSmrj7/knypkgM2kUNmXPUPRlss/dXhInNvjIAeKiMsZUs5Xl3TcMx1Sn5se09NeWjIrM9p4LjAN9dcgbMOFryYpJQ+7d2PywRIptOiTSh3rjcODFju8RJTsK3aLgAQ//kRhBhm+L5S6PMemQNRfKqLT+IqDQhkMUwcHTnh0gRz1JZuasQAYQ8oPySY2FdzrovLheviloCHpgykViCt3QKGfcyu1Hma4d7bCURLsho20mX/iDvLUWRss8UgZ+LqR1/HJI2tyLtRgwshZM44slvw4e7WafEJ+eWtyIbagWFLC2MOo26594XhUwK3L5ZocjtFo9/V0pB96qiyvd4eKD/aCkTukicP7fnozWPyS5h3h3QftLJMXH/K0C0KhYyzuG0+T/aj64KVMQp637NAq3EGOFZhXzZvmd5X/34CY94v/KZRrlVE9VxlxTRueNTQQ0bigzRaQoDwLF6vN1jCW/aKyjimDRTgzQf9e8ZROJPKDwEg5S8XVMKV5pZ/YUuZ0wFWD5XHg7dwXz738R0yS5q0B4AQOWY8j32cErW7HiRt6J72vqvoOsOu6bmvSYQ407s/XBcG+kdMEM6NkJ8ZQalfsME/tFuw0ZC5vFp8+jtBmZHcDFl35i6ZMaiz6uIA34N42KulQipgHuqztPAp/rYXyEK0RHWQ72/p+tlHDUY6LiA0zRt+k1E5xDbblqDnP6pmnfCR0BHVaMdhR7SRwa+kvIjG+uG9zY+0SFPmtrHpGRM915vVjTCgjNfEWiFh5EGWtJswsY8uX8bdCUeCs/8lA9xzouxjfQxA86fNYuaCJMFE31KK8=" + }, + { + "id": "53d903ba-6508-45b8-b48b-b3d00d3ed07a", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "部署与配置", + "description": "deployment-configuration", + "prompt": "创建详细的部署和配置指南。基于Dockerfile和docker-compose.yaml文件,说明如何构建和运行Docker容器,包括必要的环境变量(如serverName, gatewayAddr, 数据库连接信息)。解释app.conf配置文件的结构和各个配置项的含义,特别是与代理池、消息队列和数据库连接相关的设置。提供本地开发环境和生产环境的配置示例。文档应包含使用docker-compose进行本地部署的完整步骤,以及如何通过环境变量覆盖配置文件中的默认值。同时,说明build.sh构建脚本的作用和使用方法。最后,提供部署后的验证步骤,确保服务正常运行。", + "order": 5, + "progress_status": "completed", + "dependent_files": "deploy/Dockerfile,deploy/docker-compose.yaml,conf/app.conf", + "gmt_create": "2025-10-08T20:04:49.4126903+08:00", + "gmt_modified": "2025-10-08T20:08:54.4904132+08:00", + "raw_data": "WikiEncrypted:0IKfLNOWe9mZfG1jVts3w/wJu3YIP6+M0pmbICT8qHHN+JclDh3MoqOR1ZyeD+ej10Oi8PRJBW97X4s3q3IqFaiuys2xbl6eVDdT0B1MfTCDuBVTV9ACjY7VtBb7FBC0IcVcUQBob3odCrU3Ve/Zwzmr5voZ0hTxTg5HaVvm/5qmK/J4Inwe3NUANiWKByDQOErXG4DDzlVkLQyrl32yRO53NyOrOAdGlZNHHqQOeh1A1iTbWm94DdB6Qy7siKC6m2EuUqhK1mHrY0p3axbqeHYGq9F8ScuG0f0c91Th3p5LHzimNaEPBh6rx4O6PJGSlwMDz4L4bkfXiNa0sitpvB/hcB97KaKUp92KkJ6/3tFkv2p3wx/MeD8DZq4e6ZivuG/7jyRoLNFJ6r4KKzd+Oxd6z6kEBLtpLn0XBkx6rWsGzp5gnApbfbFlPdDIcgKCWNqTkZWuPL1nKQbzECovb2cHEE2KS9nnUIq+0PvkGh0X2P4c/77P4Agv/kEwfJJP2zMx9Bp6HdYDIi6/IldvScHKus1CRM3HKJs0Mo2s3okgj5X9NTZrZiI8M9tNaanvnESUkks5qpVtOpFzlCueFquwXbKyxN/oTgoRTmQN4mtb6X77XqT8mQKv5rfC3be6hmA1usBMwsDSM0/Zg3UKfaEMTXZfxq6vY2bPz9prbnXDV8I2m605vU2ReT0Y8FoAQzeTyy8JzY32cjnf7M+QWX9pfwjc9bQuUmUO6FwgdR72aOqFX1Y6phelwC1DSHk71X4wCbc+oVcZ2p/qtnuHt/yPeR3q0/NGXEH/dNRuKXWw4jll4cIHPeL1t1bR6ti+dWKiEZ1OpyO1Yk1fX7ccPgwuMMBYe+12KpeOiPPzaBCv+s19T1GKwpFBNQ67un8/+y6Cie8Sn3QjrpNgeOzcTVCGbqiPB5ReOGPt1J6IspUgG1CHqmilOJLlibA5rA2zEM5QqHglIpPrHwHMXNVrcwaCZvMRseRreSUo1qTzzBI3e7FAYWioMBEPupkKN9UDqvitC/umf3SCIoJdyB+YPF+Cf7CMF59l6Yirba17qZS93uhz/x89j7amuOJG6bGgsE6ZZo4sWJAv4pfVoP14dFYyk6E9Roqf+QWHVDnfpMsbzQcL95ev8oaLSRpnVTVKitmAWvoox5twvHQ/keXoJX3AQkmkmsd13+9xzffFQVvGz7qkk3koL1yyh1SyQgEXg5N/4ZZ1aOwVjDm5tLocpKlRM4Snh/2TrZgAIU9DylwVFr3+XnR3li1aMJoRVsiZT+QriavqWRzIkbEDk5rFwjcIrZqyTDAJIR7YhnsCR6aXaXsWnRWQSJiZw/rsRE0SyCSs10bRo1Q06MTF2J/MMQ==" + }, + { + "id": "7c85b76d-1a83-4bee-b42c-66966af08071", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "开发者指南", + "description": "developer-guide", + "prompt": "创建一份面向开发者的入门指南。指导新开发者如何设置本地开发环境,包括Go版本要求、依赖安装(通过go mod tidy)和数据库初始化。提供从克隆仓库到成功运行应用的完整步骤,涵盖使用build.sh脚本构建和使用go run main.go运行的方法。解释如何使用提供的Docker Compose文件进行本地测试。指南应包含调试技巧,例如如何启用pprof进行性能分析,以及如何理解main.go中的初始化流程。此外,提供一个简单的‘Hello World’级别的代码修改示例,比如如何添加一个新的健康检查API,以帮助开发者熟悉代码结构。最后,介绍如何运行测试套件(go test ./...)和查看覆盖率报告。", + "order": 6, + "progress_status": "completed", + "dependent_files": "build.sh,main.go,internal/utils/proxy_pool.go", + "gmt_create": "2025-10-08T20:04:49.4199566+08:00", + "gmt_modified": "2025-10-08T20:09:12.3147905+08:00", + "raw_data": "WikiEncrypted:F3QgleoEfoy16cQggYe9C5IaSqlGa9MAZLOFAWytoRMydW9CaKFacxmHFMFvq4MO4qJbomNzYz9hncXLdeBzq3fY6ynWvh0mBHFyX8UaL8b0wcWXSnuQ/e2L5ieDCeQZu4eHwClNmgAFFVxIE7fwq4P/L0Ouy8aZcek0QVX1T6OjcDp40oLyJS1lZWkB1MVrUI+5D4Rzp37Zb6zI+Z7GMLyfoDaNVlCuD8UMpYnMLTp6jym82WFZkCkD4xPJeB0MFTcG3qY2tIb5Bvvml7+yBuFFaIWKMSTNe8DNbKKSv1zzd7LWsXysYu48sFuNHIQl2narvUN8BeztzdNbnHeNafVTc6c558mr9U2RG1Ew6+zaIQ13J9VmLkDiNntBnxh1ug9tmnU//oO/P/XELKNI88btsp9+0VH3tljWocxnIg30WamPl1YDZ3v7njd60bFDOIyEJXwG4X6BcgKG8xc9hW1TTq/sqmzSng/sPGGAMPkH2PYUr2va7br7VORJP1uyyapNBLwIVKVnsldfKis7LHmYYoalh4+5X35XZJ8/vgj1NmCm7o4VzGj7gk8hlURFR1bQN4xEy9Tf67h6sMSkczXXl6YrftsVpaqhW14dfzNiKgYVHSAB+N/xNMPbilYCU2Vy4w03DHTZ2qDqmTyGalMZINYYEKdjXpWfuPTBFu/eK1FUfEW9IVY2jHkNBOaUNpwsY9WvHpirQPOXpIh0snPx/rL7520jLPYtjFXNCFKIrrzOpIMttjrvAxY7KRaY/otXIhRnTPT10NnT6Woo30DJRjtK6fpiTrQleDHYs4QhwzQLntO1XpQjRfkZvOHfQF6/mXE/FDvSZ2Eqm/sX8L+kJI5QPjI+ukL3Gc13zrsvCv9gEI3NAfl4hHpY1NoKijDd13GkskRlv6bXZvKy/WlfoZvqPzDENonheHr7Bywruul5cNFzsKeJ/RV7eNJcYelIpMxMU2IcyTwgEWjPrBqLGdxEFCKQ8LB+iPjazcE7qBVJspsHGnpYgaaJY5kMPHjP7tV1R4HlTg7kH0RlC8YWEiFDUAjKQr0NuJ+1pWPuFbBI89fgEOyObujf/16eblMfgE8ghCEyK+5QN7Gcj16rw55Y6i3gom+LRg7cFMCQAHgQna3BS9TO1NqGHNg4pTJh8+wLuCNa5U1v6Yrgo2Vjhwj/tHK4JDsSV11m8AraFoTXlxLYqcz0j+gLi1Rs3r9u6sxgjdnCO/AHKLg4dCY7FMO7sztU8rXzMEEyGXQWOGapCz5AjLOuYZ0RvvNkcJc6EtU4IELS2/piPGcJOk1jIFBLIlzPDVGMQZ21mBFPsN8i2jTa5TdvsnIClnnsL8wzJZ1FGgCTZ8MTW4wVWpAlTDLtxTPMeOAAeKcfFfQ=" + }, + { + "id": "331580be-858a-4589-a919-b92058d006ec", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "第三方支付渠道集成", + "description": "supplier-integration", + "prompt": "创建一份详细的第三方支付渠道集成指南。以supplier_interface.go中定义的PayInterface为起点,解释开发者需要实现哪些方法(如Pay, QueryOrder)来集成一个新的支付供应商。通过分析apple.go和jd.go的具体实现,展示如何处理HTTP请求、解析响应、处理错误和实现重试逻辑。文档应指导开发者如何将新的供应商实现文件添加到third_party目录,并在系统中注册它。详细说明如何处理供应商特有的认证机制、API限流和数据格式。提供一个分步教程,从创建新的供应商结构体到编写单元测试(参考*_test.go文件)的完整过程。同时,讨论集成过程中的常见陷阱和最佳实践,例如如何保证交易的幂等性。", + "order": 7, + "progress_status": "completed", + "dependent_files": "internal/service/supplier/supplier_interface.go,internal/service/supplier/third_party/apple.go,internal/service/supplier/third_party/jd.go", + "gmt_create": "2025-10-08T20:04:49.4278395+08:00", + "gmt_modified": "2025-10-08T20:09:49.9517291+08:00", + "raw_data": "WikiEncrypted:ywogS1mtCJIl+oV7mNfjwB2ZQVNfkgJnqF/1L9l94PPI4nVaCUND6Ba/xPhgcy1ixLEENjLmt2SwM42O16RTFsyDUuIunmYOrznVtObrwE4CcrFFlAe52xCO6ES0KjMtkwt787qMvDW+cJKqvyTAFBojgcPuK3SDfK9Mec2DEpO1LfnYbqe9mqasmsSRhtAxiS60oBy5gyI4LL4kgv5l96szPTwtkZcGiZ+Ew5YDK+HRRh930XL4HBSoOo52r1VECCSez5WhwkfO4au7pSVeRrq8SRpbDnH5OaOe4oiHJk9au06vzz8NnjShH77ed/BKVPqC1nsRJxt2upXuX4zK8Eaph56pay4AMAGtd6d15+mqVcRcNhyWpNj6MmNtQv9gE7BuIn7nZor3PKc4v3rOGGRNlsa9khExQc/5CA6jhWlPiID+9fOlOqISgTivnhjNXiuAyEZgd53X7TDrPcjb8gPwWFX7g75dxn/9bfXFsfwBCtzHdl1/NvbNrZwSY0LxjjKSiqY47twiZp1UUG/8Epf9ykv0iGOcF9EuY4k5aUcTLMa2pikZymA2yBhnCXqdrLp8rHKyBLL/0jeMabvVGDrF+cwGKjQs54fQniOe30ijNO90Mu5Xhv0jyTFoDuZoRdnKMsFuBJDfOdW48OsDc6bXXy5ySH9Zoz5ggXZQ3AVwG+1MDG/2dJ30hRSmpURyY91k07LxX5j7lHaxvdKHUozGcJJmT7elY7WJlWg6n45AYSpytJ7zrMSZCm8+hWYHvbRE7MNOggcdoAbpbL2R5V/jR2g/0HLCI8cbXgsAvEJDhWgdcKxw+yd5hbLeNhTFMzkTqGeCP/AL+4ePNQn9xinm8tEc2IBPlLxPWff5Bx3daE3u0gz1E0aPbF2mKp52xV5l27W4/XviATRAoyyol5CREMVn1qxkSQ34IEto3dUqr2q4BVFKnXfzzbuhnFe9wDuTIyqzQ8f7vycmn9F3B5GBAdHKVhkEZ9w+IfbYJB2kOyETLYtsP8mtWAyh3xz5HS/U9OXIajAOQmGszeqnoenAh9REhMe6zuj35fC6+/7gqduAjJ/aA/8xgWiaNCovrrMfXwU76yCRLuqg9bBJ9RsdY8xqnuqJE4i+XZUueq9d65kKFpInLchwpL2EETEKmNpBuUAniUOWoOe6RDNitu8ODD5YbYKukPzvHwq6NhH2+xK0JKXb7jWsytKOejz+BQ/HpB9b5ds7ysGL/z68X0QMNrykSZNc55DM+RxJ527isaTQD4Lb99xas6cHEDsDLbaRqFtX965E+fXGU9xunmtCdMtB0fJLfYgdrV/wQZNQ9k2hTTrRAEetYOL0/iSpsDnBQK9VSjQ2hTb297pPD9YadKQ2tfF39C+GFDgWTSUGUPjDvjWNVURGlNEorXhTGydT04HDQMq9DuKzJqxdbEeDrNisQFzpWY4hdzx6oBDRzW5v9k0pmFYmaI71S3WTKc1VGp3zgEJqBL3LWfnD/kQ7oUJOs8KD5QMBLSNg7vadyzFL5t+edYSy/0uG4OQk7/Jsmv9jmFsqkJCoFdLMoSfwOEEz61PNZm5qdmD9E3uUnR6KDx7Iri3bDtw3VwhS" + }, + { + "id": "5103593b-a8d6-47a1-893e-70804c5aece3", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "监控与故障排除", + "description": "monitoring-troubleshooting", + "prompt": "创建监控和故障排除指南。解释如何利用OpenTelemetry(otelTrace包)进行分布式追踪,包括如何查看和分析调用链路,以及如何利用日志(logs.go)进行问题诊断。说明系统生成的关键指标(metrics)和如何通过Prometheus进行收集。提供一个常见问题列表,例如支付请求超时、回调失败、数据库连接池耗尽等,并给出详细的排查步骤和解决方案。指导开发者如何使用测试文件(如pay_solve_test.go)来复现和修复问题。文档还应涵盖性能监控,如如何识别慢查询和高延迟的API端点,并提供优化建议。最后,说明如何配置告警规则以及时发现系统异常。", + "order": 8, + "progress_status": "completed", + "dependent_files": "internal/otelTrace/init.go,internal/otelTrace/logs.go,internal/service/pay_solve_test.go", + "gmt_create": "2025-10-08T20:04:49.4359827+08:00", + "gmt_modified": "2025-10-08T20:09:55.1250682+08:00", + "raw_data": "WikiEncrypted:HL3VqGjXq8A3aGeLxAjVPseClgy+ysLjZsoexAfPX3D+iOtNevnlQtZ/dd7X4on1/Fyf+3QZwDuK3nCfC7OOkg86/p0JWgywkQarmHhcigUgldYHYgPlswdqtUiJ71c2S+Gi4+wXeIwcNjykzkwdznLlXNcmVsr1v+p768Zyqop5mDO8xnxo+XQBHtJ3YXCOljmnoJXjrC3ZNNtCYt+KHXxwijCvLJnkvhAeXKn2MpU2qxKKneMv/5/xOC4nYR1g3yi0czu0l70Sc+SVwlXl1XJ57EccIG85G06Ky1blzAaQtrV9k9tyKYV3GuWX30m8MNQS+eTO/O6Cj/tu+oitNGS5ATfwtsWcv4k5ZgeHbWOrx/OnQQEdrw9VYm9aBtkmmBzfg256bR+j3pkRtz4gf9R2ANU5iozq9EJHUoRb2l9xy3Tez8lILslubKwODlRiP40RRAmy4fVQTSfGwiVA0kCVxlb4NCqisrIYzmSmryK9AbZJUR7UZ1gKn6rltyP4OpamSFle5UrthA0CVGZKxpCSFUu43Vx0/K7bOz94BThDgparsv3hko5xVsWb62yce2lK1xTdrjMaVwPsYwD//Wme/bKI0RJqRgSaKWguYPlNMcVFe/nBqUl/f9fS2ni87qSX4Qt1wbk5Jbm8wygD5GuXDygRVTc27t6udRhZ3l3iY/9XHmUdCDfeYtUeyB0eyJAVE/iYu/xngnYkZPWcsngoo1zJGz+Sl1TrkmQYCRlkUtJpqo5ekNSf1q9Oi5/HZK6qgHHggDmrkr7ikiGIjz8fDvPpmk4GGGOKsnmyn9gEGvHgXb8S1ZOVXyL03Hyq0FK4azgII7hV2IM3BEzOL1hP2oIGGtLaqXISqvF2llfFL7WyHU98ET/YNgvenhdF4/HIx/K1wAmmtsmpepTd2gO/TQEDgigicw1PENvvfVcsfgXJrb9PH1psCfkkXepk2rx04OI8X9Q8csBVtfMfqZiOwnI/H+zZ+U+tdopVwPeHohjLgpoOXlgHQUYqclbISkvFqQnll8bEQaQgiAczs4TEH4lKKeKKHoO3qKH5KkYhqILXKT8FIfwTIoiskg/i+rDcZ8tDR19Hb+vLkDbbA59Bh0RzLwJzNPbcU4Hodjg/5MvSkc9ZXAFrbu3f9Mw+1QmC1y1fu0M9PuGMI367bU0yBbiGis4BAjOBb8GnLxmtifOnd+58XC7X32FyIdQOjoG+1UUlDQ9FzuLoDXxHuXa06LYt0i2fd6qkAzH0ETXaevaA5h5jHR74NAEJGKtoBVfezd4cDoVyUkv9OQq/zzUwqNMr2ys0AndefGVHqCp5n3xszeLwYL3TNzeovTq867z+h0+MUeOvupXt3gh6Q24BKxBVLjN9n0ciQaTD9NT1Q4nFMv3TrGD+YptlHFkBTDjYJQk8FnRTPfJ+96Xst/ni6IWFMND0a2bLTLtWY9w=" + } + ], + "wiki_items": [ + { + "catalog_id": "3f5378b4-a8c2-4361-90a2-caf79aeba7fb", + "title": "项目概述", + "description": "project-overview", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "a9f244fa-cb21-4a31-85c5-74ee22535241", + "gmt_create": "2025-10-08T20:07:08.6767978+08:00", + "gmt_modified": "2025-10-08T20:07:08.6884683+08:00" + }, + { + "catalog_id": "80fb1e42-5bd2-4870-8b88-77d31ff5c478", + "title": "API参考", + "description": "api-reference", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "89d888b3-2b22-4be7-8c3e-66e1f9cef86c", + "gmt_create": "2025-10-08T20:07:10.9494972+08:00", + "gmt_modified": "2025-10-08T20:07:10.9680712+08:00" + }, + { + "catalog_id": "576b2803-bcc0-4769-89b3-54c89e6b7381", + "title": "技术栈与依赖", + "description": "technology-stack", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "013b2790-e5e2-4879-8a97-c5dee7adde89", + "gmt_create": "2025-10-08T20:08:07.0438986+08:00", + "gmt_modified": "2025-10-08T20:08:07.1467933+08:00" + }, + { + "catalog_id": "1ccdc69d-fc3b-4d08-9be6-169095e4a163", + "title": "核心架构", + "description": "core-architecture", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "7424e713-8de3-415b-ab24-f02a1102bdbc", + "gmt_create": "2025-10-08T20:08:12.4384285+08:00", + "gmt_modified": "2025-10-08T20:08:12.4586942+08:00" + }, + { + "catalog_id": "a5d56738-c20f-4178-9f81-d01bb592f194", + "title": "数据模型", + "description": "data-model", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "6e2e98a9-36f3-46c1-b2f2-db52c4526f11", + "gmt_create": "2025-10-08T20:08:34.0144975+08:00", + "gmt_modified": "2025-10-08T20:08:34.0353959+08:00" + }, + { + "catalog_id": "53d903ba-6508-45b8-b48b-b3d00d3ed07a", + "title": "部署与配置", + "description": "deployment-configuration", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "d2d80765-26c3-4c0b-a302-612693077838", + "gmt_create": "2025-10-08T20:08:54.4805496+08:00", + "gmt_modified": "2025-10-08T20:08:54.491486+08:00" + }, + { + "catalog_id": "7c85b76d-1a83-4bee-b42c-66966af08071", + "title": "开发者指南", + "description": "developer-guide", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "87ee006d-1361-4097-943f-fd617b437f89", + "gmt_create": "2025-10-08T20:09:12.3048385+08:00", + "gmt_modified": "2025-10-08T20:09:12.3157912+08:00" + }, + { + "catalog_id": "331580be-858a-4589-a919-b92058d006ec", + "title": "第三方支付渠道集成", + "description": "supplier-integration", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "3f94dede-2298-4788-89a2-f4b817701e01", + "gmt_create": "2025-10-08T20:09:49.9419345+08:00", + "gmt_modified": "2025-10-08T20:09:49.9524517+08:00" + }, + { + "catalog_id": "5103593b-a8d6-47a1-893e-70804c5aece3", + "title": "监控与故障排除", + "description": "monitoring-troubleshooting", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "77d3b3e8-3b5b-4065-a83c-cda3fa14b5b5", + "gmt_create": "2025-10-08T20:09:55.116388+08:00", + "gmt_modified": "2025-10-08T20:09:55.1261123+08:00" + }, + { + "catalog_id": "ff8a9c9d-2dc0-433a-a1d4-b84ee2141635", + "title": "订单模型", + "description": "order-model", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "302aea38-1949-48e6-bd95-96cb17b84d12", + "gmt_create": "2025-10-08T20:10:13.3069178+08:00", + "gmt_modified": "2025-10-08T20:10:13.3189892+08:00" + }, + { + "catalog_id": "3d1b720f-a641-456e-94d0-ff9db2b5568c", + "title": "Docker部署指南", + "description": "docker-deployment", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "3f30d007-e6cc-4636-8ab7-f10562baff6a", + "gmt_create": "2025-10-08T20:10:46.0191897+08:00", + "gmt_modified": "2025-10-08T20:10:46.0290875+08:00" + }, + { + "catalog_id": "0fd4a109-43f9-4cea-9416-4cd2bcafd325", + "title": "支付API", + "description": "payment-api", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "0fb51e95-8a1d-45fe-96b2-632c00da5541", + "gmt_create": "2025-10-08T20:10:53.9304568+08:00", + "gmt_modified": "2025-10-08T20:10:53.9579352+08:00" + }, + { + "catalog_id": "a21144d5-112d-4642-a874-64fb8a1ea84f", + "title": "Beego 框架集成", + "description": "beego-framework", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "13bd83fa-402e-438b-a012-6d53eac7c39d", + "gmt_create": "2025-10-08T20:11:20.9462141+08:00", + "gmt_modified": "2025-10-08T20:11:20.9577989+08:00" + }, + { + "catalog_id": "7cc42a3a-553a-4702-9eaf-b76dd3628a17", + "title": "支付服务架构", + "description": "payment-service-architecture", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "026c8458-a7b5-44cf-b052-10b1cd6604f2", + "gmt_create": "2025-10-08T20:11:36.0414447+08:00", + "gmt_modified": "2025-10-08T20:11:36.0519241+08:00" + }, + { + "catalog_id": "062cb25b-369d-43d0-b6d3-96447d99b3e9", + "title": "商户模型", + "description": "merchant-model", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "b527099a-0510-438d-a4ec-b8ed8642ae8e", + "gmt_create": "2025-10-08T20:11:59.3046725+08:00", + "gmt_modified": "2025-10-08T20:11:59.3164336+08:00" + }, + { + "catalog_id": "fd2a2cba-0887-44b8-93c2-9cc9e520daae", + "title": "OpenTelemetry 分布式追踪", + "description": "opentelemetry-tracing", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "d0e098cc-486d-48ae-99b6-dae8bd81b609", + "gmt_create": "2025-10-08T20:12:14.104241+08:00", + "gmt_modified": "2025-10-08T20:12:14.1189211+08:00" + }, + { + "catalog_id": "c7928cce-8e94-4629-be4d-3af7f5d251bb", + "title": "查询API", + "description": "query-api", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "75b363d5-4074-4921-9ada-579b8f5a30c4", + "gmt_create": "2025-10-08T20:12:22.877929+08:00", + "gmt_modified": "2025-10-08T20:12:22.8891039+08:00" + }, + { + "catalog_id": "74304c2d-414f-40ca-9155-fde8c06a0128", + "title": "配置文件详解", + "description": "configuration-file", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "3b453233-b2ab-4942-9a6c-d92a5a3897c0", + "gmt_create": "2025-10-08T20:12:50.0833468+08:00", + "gmt_modified": "2025-10-08T20:12:50.0945204+08:00" + }, + { + "catalog_id": "316c7f5b-5e53-4322-9376-f94f1cc1ba37", + "title": "账户与代理商模型", + "description": "account-agent-model", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "f5af27a6-1bd2-4346-a7a8-2682705f09c5", + "gmt_create": "2025-10-08T20:13:19.8684904+08:00", + "gmt_modified": "2025-10-08T20:13:19.8881676+08:00" + }, + { + "catalog_id": "0d7875e0-1107-4966-8a99-a6d24685c88c", + "title": "供应商集成架构", + "description": "supplier-integration-architecture", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "16f1ef56-d692-41dd-84d7-c41790f98abb", + "gmt_create": "2025-10-08T20:13:46.8661406+08:00", + "gmt_modified": "2025-10-08T20:13:46.8783305+08:00" + }, + { + "catalog_id": "715db9db-8d32-4ea3-926a-b56c98ea6d8d", + "title": "数据库与缓存系统", + "description": "database-cache", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "8a821f9b-5ad9-4602-96c2-724299a01a8b", + "gmt_create": "2025-10-08T20:14:05.025848+08:00", + "gmt_modified": "2025-10-08T20:14:05.0416874+08:00" + }, + { + "catalog_id": "8600f0c5-e3cf-489b-a029-725506750564", + "title": "代付API", + "description": "payfor-api", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "5c05b03a-d7c9-43f5-94c6-1f4ea2793f19", + "gmt_create": "2025-10-08T20:14:21.0044301+08:00", + "gmt_modified": "2025-10-08T20:14:21.021717+08:00" + }, + { + "catalog_id": "3f59a04d-339e-40c5-8c7f-c98ed6ef6d8b", + "title": "环境变量管理", + "description": "environment-variables", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "93cae8db-9a04-407a-8446-250cdc33f661", + "gmt_create": "2025-10-08T20:14:26.0779486+08:00", + "gmt_modified": "2025-10-08T20:14:26.0886312+08:00" + }, + { + "catalog_id": "c0f73068-9c54-4cc7-ae03-811f69af12c9", + "title": "消息队列与异步处理", + "description": "message-queue", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "3077240f-f00b-4f59-a8ce-8991408c4b96", + "gmt_create": "2025-10-08T20:15:18.9536664+08:00", + "gmt_modified": "2025-10-08T20:15:18.9619544+08:00" + }, + { + "catalog_id": "8af4b541-5a66-4fb9-86b1-7c95c9f63ab0", + "title": "任务调度架构", + "description": "task-scheduling-architecture", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "f0a4a14b-8948-4372-a8b7-6974e4286083", + "gmt_create": "2025-10-08T20:15:38.5917719+08:00", + "gmt_modified": "2025-10-08T20:15:38.6066131+08:00" + }, + { + "catalog_id": "15483189-42f7-4bbe-89bd-55f035c33ccf", + "title": "回调API", + "description": "callback-api", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "70b6c90d-240f-4eb3-abc6-50fb7add6fc3", + "gmt_create": "2025-10-08T20:15:38.799372+08:00", + "gmt_modified": "2025-10-08T20:15:38.8103294+08:00" + }, + { + "catalog_id": "18826686-b467-4bd9-879d-73a780854d0f", + "title": "MySQL数据库集成", + "description": "database-mysql", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "9c7904f8-0b4a-422b-806d-55c96bec2fe6", + "gmt_create": "2025-10-08T20:16:01.6742931+08:00", + "gmt_modified": "2025-10-08T20:16:01.6864756+08:00" + }, + { + "catalog_id": "0ebb9117-99a5-4092-862c-49ee70ccfee0", + "title": "初始化与资源配置", + "description": "opentelemetry-tracing-initialization", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "b5f75438-5c24-4f0f-be95-f857806fcfaf", + "gmt_create": "2025-10-08T20:16:13.1207896+08:00", + "gmt_modified": "2025-10-08T20:16:13.131653+08:00" + }, + { + "catalog_id": "7f560146-d4af-4131-8722-dcf698604b6f", + "title": "Redis缓存系统", + "description": "cache-redis", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "2500aa21-fe32-4057-a5ad-11fbd4d19546", + "gmt_create": "2025-10-08T20:16:35.7490861+08:00", + "gmt_modified": "2025-10-08T20:16:35.7602342+08:00" + }, + { + "catalog_id": "b99f6bc9-1a5f-4e15-82c4-3f4c27eb0724", + "title": "HTTP中间件集成", + "description": "opentelemetry-tracing-middleware", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "4a9995be-1002-4a48-bf07-8b4f725756d0", + "gmt_create": "2025-10-08T20:16:57.8698101+08:00", + "gmt_modified": "2025-10-08T20:16:57.8804333+08:00" + }, + { + "catalog_id": "40a4568f-d8f6-46e2-a301-107062e68778", + "title": "Span生命周期管理", + "description": "opentelemetry-tracing-span-management", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "b2cf330f-309b-4fa5-980c-c5809a143195", + "gmt_create": "2025-10-08T20:17:08.3980224+08:00", + "gmt_modified": "2025-10-08T20:17:08.4091288+08:00" + }, + { + "catalog_id": "556f07d5-845b-4291-9b39-b0872940a3a8", + "title": "日志与追踪上下文关联", + "description": "opentelemetry-tracing-logging-integration", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "047d142f-ec46-4f80-83d3-c377a86858b8", + "gmt_create": "2025-10-08T20:17:17.7986613+08:00", + "gmt_modified": "2025-10-08T20:17:17.8131445+08:00" + }, + { + "catalog_id": "00f89107-2ade-477a-b10e-0c444161fdbb", + "title": "资源标识与上下文配置", + "description": "opentelemetry-tracing-resource", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "e50eff25-5123-4c73-8a3b-487293043f2f", + "gmt_create": "2025-10-08T20:17:55.1005301+08:00", + "gmt_modified": "2025-10-08T20:17:55.1156575+08:00" + }, + { + "catalog_id": "a85503ac-22f7-4a7c-946f-359954121de8", + "title": "追踪导出器配置", + "description": "opentelemetry-tracing-exporter", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "ed7bbb93-3e0c-49fe-b1dd-a92d8176638e", + "gmt_create": "2025-10-08T20:17:57.5755162+08:00", + "gmt_modified": "2025-10-08T20:17:57.5865498+08:00" + }, + { + "catalog_id": "1fedbb41-1015-4ec4-aaa3-c732e30b12f6", + "title": "采样策略与批量处理", + "description": "opentelemetry-tracing-sampling", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "243ba92b-7b56-4596-9c54-31905f65e471", + "gmt_create": "2025-10-08T20:18:01.3341913+08:00", + "gmt_modified": "2025-10-08T20:18:01.34411+08:00" + }, + { + "catalog_id": "25edcf0d-932e-4a7e-ac78-00f9888b6ac7", + "title": "分布式上下文传播", + "description": "opentelemetry-tracing-propagation", + "extend": "{}", + "progress_status": "completed", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "id": "99e9dc6d-e943-4712-a961-7a053872ad8f", + "gmt_create": "2025-10-08T20:18:48.5863741+08:00", + "gmt_modified": "2025-10-08T20:18:48.5968345+08:00" + } + ], + "wiki_overview": { + "content": "\u003cblog\u003e\n# Kami Gateway 项目综合分析\n\n## 1. 项目介绍\n\nKami Gateway 是一个基于 Go 语言开发的高性能支付网关服务,旨在为多商户、多通道的聚合支付场景提供稳定可靠的解决方案。该项目主要处理第三方卡密充值、订单调度、代付请求及回调通知等核心业务,支持爱博、京东卡、天猫游戏、沃尔玛等数十种第三方支付渠道。\n\n项目的核心目标是构建一个高可扩展性、高稳定性的支付网关系统,通过微服务架构实现业务解耦,利用 Beego 框架作为 Web 服务基础,并结合 Redis、RabbitMQ 等中间件实现任务队列与异步处理机制。系统集成了 OpenTelemetry 实现分布式追踪,具备良好的可观测性与运维能力。\n\n本项目主要面向支付平台开发者、系统架构师以及需要集成多种支付渠道的商户技术团队,适用于需要处理大量支付交易、要求高可用性和可扩展性的商业场景。\n\n## 2. 技术架构\n\n### 组件分解\n\nKami Gateway 采用分层架构设计,主要包括以下几个核心组件:\n\n- **API 层**:处理 HTTP 请求,提供 RESTful API 接口\n- **业务逻辑层**:实现核心支付业务逻辑,包括订单处理、支付回调等\n- **服务层**:封装第三方支付渠道的具体实现\n- **数据访问层**:与 MySQL、Redis 等数据存储系统交互\n- **基础设施层**:提供缓存、消息队列、分布式追踪等公共服务\n\n### 设计模式\n\n项目采用了多种设计模式来提高代码的可维护性和扩展性:\n\n- **依赖注入**:通过初始化函数注入配置、缓存、消息队列等依赖\n- **单例模式**:用于管理队列管理器、代理池等全局资源\n- **事件驱动**:通过事件总线实现订单创建、处理、失败等事件的发布与订阅\n- **工厂模式**:用于创建不同类型的任务处理器\n\n### 系统关系与数据流\n\n```mermaid\nflowchart TD\n A[客户端] --\u003e B[API 层]\n B --\u003e C[业务逻辑层]\n C --\u003e D[服务层]\n D --\u003e E[第三方支付渠道]\n C --\u003e F[数据访问层]\n F --\u003e G[(MySQL)]\n F --\u003e H[(Redis)]\n I[第三方渠道] --\u003e J[回调处理]\n J --\u003e C\n K[RabbitMQ] --\u003e L[异步任务处理]\n L --\u003e C\n M[OpenTelemetry] --\u003e N[分布式追踪]\n N --\u003e C\n N --\u003e D\n```\n\n## 3. 关键实现\n\n### 主要入口点\n- [main.go](e:\\projects\\kami\\kami_gateway\\main.go)\n\n### 核心模块\n- [router.go](e:\\projects\\kami\\kami_gateway\\internal\\routers\\router.go)\n- [pool/service.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\pool\\service.go)\n- [queue/manager.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\queue\\manager.go)\n- [order_notify.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\notify\\order_notify.go)\n\n### 配置方法\n- [app.conf](e:\\projects\\kami\\kami_gateway\\conf\\app.conf)\n\n### 外部依赖\n- [init.go](e:\\projects\\kami\\kami_gateway\\internal\\otelTrace\\init.go)\n\n### 集成点\n- [aibo.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\aibo.go)\n- [jd.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\jd.go)\n- [apple.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\apple.go)\n- [walmart.go](e:\\projects\\kami\\kami_gateway\\internal\\service\\supplier\\third_party\\walmart.go)\n\n### 组件关系图\n\n```mermaid\ngraph LR\n A[main.go] --\u003e B[router.go]\n A --\u003e C[app.conf]\n A --\u003e D[init.go]\n B --\u003e E[控制器]\n E --\u003e F[service]\n F --\u003e G[第三方支付实现]\n G --\u003e H[第三方渠道]\n F --\u003e I[数据访问]\n I --\u003e J[MySQL]\n I --\u003e K[Redis]\n D --\u003e L[OpenTelemetry]\n L --\u003e A\n L --\u003e F\n L --\u003e G\n```\n\n## 4. 关键特性\n\n### 功能概述\n\nKami Gateway 提供了完整的支付网关功能,包括:\n- 多渠道支付支持\n- 动态代理池\n- 异步任务队列\n- 自动订单调度\n- 分布式追踪\n- 灵活配置\n- Docker 化部署\n- API 回调处理\n\n### 实现亮点\n\n项目通过创新的订单池机制实现了高效的订单匹配和处理。订单池服务(OrderPoolService)作为核心组件,负责管理用户订单和生产订单的匹配过程。系统采用事件驱动模型,通过事件总线(EventBus)实现订单创建、处理、失败等事件的发布与订阅,确保了系统的松耦合和高可扩展性。\n\n异步任务处理通过 RabbitMQ 实现,订单回调消费者(CreateOrderNotifyConsumer)监听消息队列,处理订单回调任务。系统还实现了智能的重试机制,根据回调次数动态调整重试间隔,提高了系统的稳定性和可靠性。\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e 初始化\n 初始化 --\u003e 运行中: 启动服务\n 运行中 --\u003e 处理订单: 接收订单请求\n 处理订单 --\u003e 匹配订单: 进入订单池\n 匹配订单 --\u003e 提交订单: 找到匹配\n 提交订单 --\u003e 等待回调: 发送至第三方\n 等待回调 --\u003e 更新状态: 收到回调\n 更新状态 --\u003e 通知商户: 发送通知\n 通知商户 --\u003e 运行中: 完成\n 匹配订单 --\u003e 超时处理: 未找到匹配\n 超时处理 --\u003e 运行中: 清理订单\n 提交订单 --\u003e 提交失败: 提交错误\n 提交失败 --\u003e 重试提交: 重新提交\n 重试提交 --\u003e 提交订单: 重试\n 重试提交 --\u003e 运行中: 达到最大重试次数\n```\n\u003c/blog\u003e", + "gmt_create": "2025-10-08T20:03:05.5426812+08:00", + "gmt_modified": "2025-10-08T20:03:05.5426812+08:00", + "id": "3df72775-b038-40a3-82fb-11672047d8a7", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593" + }, + "wiki_readme": { + "content": "# Kami Gateway\n\nKami Gateway 是一个基于 Go 语言开发的高性能支付网关服务,主要用于处理第三方卡密充值、订单调度、代付请求及回调通知等核心业务。项目采用 Beego 框架作为 Web 服务基础,并结合 Redis、RabbitMQ 等中间件实现任务队列与异步处理机制。系统支持多种第三方支付渠道(如爱博、京东卡、天猫游戏、沃尔玛等),具备高可扩展性与稳定性,适用于多商户、多通道的聚合支付场景。\n\n本项目使用 OpenTelemetry 实现分布式追踪,集成 Redis 缓存与代理池机制,通过微服务架构实现解耦,具备良好的可观测性与运维能力。\n\n## 主要特性\n\n- **多渠道支付支持**:支持爱博、京东、天猫、沃尔玛、六盒、茄子、金科、善付、鲁班等数十种第三方卡密充值渠道。\n- **动态代理池**:内置代理调度机制,支持 HTTP 代理轮询,提升请求成功率。\n- **异步任务队列**:基于 Redis 实现任务队列,支持卡密提交、登录、查询等异步任务处理。\n- **自动订单调度**:通过事件驱动模型实现订单创建、查询、超时处理等自动化流程。\n- **分布式追踪**:集成 OpenTelemetry,支持链路追踪与日志关联,便于问题排查。\n- **灵活配置**:通过 `app.conf` 配置文件管理数据库、MQ、第三方接口等参数。\n- **Docker 化部署**:提供完整的 Dockerfile 与 docker-compose 配置,支持本地与生产环境快速部署。\n- **API 回调处理**:统一接收各渠道的支付结果回调,自动更新订单状态并通知商户。\n\n## 安装与部署\n\n### 前置依赖\n\n- Go 1.24+\n- Redis\n- MySQL\n- RabbitMQ\n- Docker(可选)\n\n### 构建方式\n\n```bash\n# 构建二进制文件\n./build.sh\n```\n\n### Docker 部署\n\n```bash\n# 构建并启动服务(生产环境)\ndocker-compose up -d\n\n# 本地开发环境启动\ndocker-compose -f docker-compose-local.yaml up -d\n```\n\n### 配置说明\n\n主要配置文件位于 `conf/app.conf`:\n\n```ini\nappname = jhgateway\nhttpport = 12309\nrunmode = prod\n\n[mysql]\ndbhost = 127.0.0.1\ndbport = 3306\ndbuser = root\ndbpasswd = Woaizixkie!123\ndbbase = kami\n\n[redis]\nhost = 127.0.0.1:6379\npassword = \"\"\n\n[mq]\nhost = 127.0.0.1\nport = 61613\n```\n\n第三方接口地址、密钥等配置也在此文件中定义,如 `mf`, `appleCard`, `jdCard` 等。\n\n## 使用方法\n\n### API 接口\n\n通过 `internal/routers/router.go` 可知主要 API 路由如下:\n\n| 路径 | 方法 | 功能 |\n|------|------|------|\n| `/gateway/scan` | POST | 创建充值订单 |\n| `/gateway/queryAccountInfo/:channel` | GET | 查询账户信息 |\n| `/gateway/createOrder` | POST | 创建订单 |\n| `/gateway/merchant/query` | POST | 商户查单 |\n| `/gateway/supplier/order/query` | POST | 上游订单查询回调 |\n| `/gateway/update/order` | POST | 更新订单状态 |\n\n### 第三方回调\n\n系统接收来自各渠道的支付结果回调,路径如下:\n\n- `/mfcard/notifyV2` → MF卡\n- `/appleCard/notify` → 苹果卡\n- `/jdCard/notify` → 京东卡\n- `/tMallGame/notify` → 天猫游戏\n- `/walMart/notify` → 沃尔玛\n- `/sixFat/notify` → 六盒\n- `/AiBo/notify` → 爱博\n- ...(其他渠道类似)\n\n回调处理逻辑由 `internal/service/supplier/third_party/*.go` 实现,如 `aibo.go`、`jd.go` 等。\n\n### 任务队列机制\n\n系统通过 Redis 实现任务队列,核心组件位于:\n\n- `internal/service/supplier/third_party/queue/`:队列管理、任务定义、处理器\n- `internal/service/supplier/third_party/pool/`:工作池、事件处理、通道实现\n\n任务类型包括:\n- `card_submit`:卡密提交\n- `login`:登录任务\n- `card_query`:卡密查询\n\n通过 `QueueManager` 动态创建通道队列,支持按 `channelID` 隔离任务流。\n\n## 开发说明\n\n### 项目结构\n\n```\n├── conf/ # 配置文件\n├── deploy/ # 部署脚本与Docker配置\n├── internal/ # 核心业务逻辑\n│ ├── cache/ # Redis缓存封装\n│ ├── config/ # 配置读取\n│ ├── controllers/ # HTTP控制器\n│ ├── models/ # 数据模型\n│ ├── routers/ # 路由注册\n│ ├── service/ # 业务服务\n│ │ └── supplier/ # 第三方渠道实现\n│ ├── utils/ # 工具函数(加密、签名、HTTP等)\n│ └── otelTrace/ # 分布式追踪\n├── build.sh # 构建脚本\n└── main.go # 入口文件\n```\n\n### 添加新支付渠道\n\n1. 在 `internal/service/supplier/third_party/` 下创建新实现,如 `mycard.go`\n2. 实现 `SendCard`、`Scan`、`PayNotify` 方法\n3. 在 `router.go` 中注册回调路由\n4. 在配置文件中添加接口地址与密钥\n\n### 日志与追踪\n\n日志输出至 `./logs/jhmerchant.log`,支持分级输出(debug ~ emergency)。 \n通过 OpenTelemetry 支持链路追踪,可在日志中查看 `trace_id`、`span_id` 进行关联分析。\n\n## 许可证\n\n未找到 LICENSE 文件,许可证信息暂缺。", + "gmt_create": "2025-08-22T11:07:51.6280873+08:00", + "gmt_modified": "2025-08-22T11:07:51.6280873+08:00", + "id": "e8a20657-bb01-4b74-bd31-67bf99ba82a3", + "repo_id": "154b5d19-4920-4fbb-b73a-e2620e744593" + }, + "wiki_repo": { + "id": "154b5d19-4920-4fbb-b73a-e2620e744593", + "name": "kami_gateway", + "progress_status": "completed", + "wiki_present_status": "COMPLETED", + "optimized_catalog": "\".\\n├── conf\\n│ └── app.conf\\n├── deploy\\n│ ├── Dockerfile\\n│ ├── docker-compose-local.yaml\\n│ ├── docker-compose.yaml\\n│ └── wait-for-it.sh\\n├── internal\\n│ ├── cache\\n│ │ ├── lock.go\\n│ │ ├── options.go\\n│ │ ├── redis.go\\n│ │ └── redis_test.go\\n│ ├── config\\n│ │ ├── cfg_model.go\\n│ │ ├── config.go\\n│ │ ├── mq_config.go\\n│ │ └── proxy.go\\n│ ├── consts\\n│ │ ├── road_info.go\\n│ │ └── steal_rule.go\\n│ ├── controllers\\n│ │ ├── base_controller.go\\n│ │ ├── order_controller.go\\n│ │ ├── payfor_controller.go\\n│ │ └── scan_controller.go\\n│ ├── dto\\n│ │ ├── order.go\\n│ │ └── order_test.go\\n│ ├── models\\n│ │ ├── accounts\\n│ │ │ ├── account.go\\n│ │ │ └── account_history_info.go\\n│ │ ├── agent\\n│ │ │ ├── agent_info.go\\n│ │ │ └── agent_profit.go\\n│ │ ├── hidden\\n│ │ │ ├── merchant_hidden_config.go\\n│ │ │ └── merchant_hidden_record.go\\n│ │ ├── merchant\\n│ │ │ ├── merchant_info.go\\n│ │ │ └── merchant_load_info.go\\n│ │ ├── merchant_deploy\\n│ │ │ └── merchant_deploy_info.go\\n│ │ ├── notify\\n│ │ │ └── notify_info.go\\n│ │ ├── order\\n│ │ │ ├── order_info.go\\n│ │ │ ├── order_profit_info.go\\n│ │ │ ├── order_settle_info.go\\n│ │ │ └── platform_profit.go\\n│ │ ├── payfor\\n│ │ │ └── payfor_info.go\\n│ │ ├── response\\n│ │ │ └── response.go\\n│ │ ├── road\\n│ │ │ ├── road_info.go\\n│ │ │ └── road_pool_info.go\\n│ │ ├── setting\\n│ │ │ └── sys_config_dict.go\\n│ │ ├── supply_model\\n│ │ │ └── models.go\\n│ │ ├── system\\n│ │ │ ├── bank_card_info.go\\n│ │ │ ├── menu_info.go\\n│ │ │ ├── power_info.go\\n│ │ │ ├── role_info.go\\n│ │ │ └── second_menu_info.go\\n│ │ ├── task\\n│ │ │ └── task.go\\n│ │ ├── user\\n│ │ │ └── user_info.go\\n│ │ └── init.go\\n│ ├── otelTrace\\n│ │ ├── circuit_breaker.go\\n│ │ ├── consts.go\\n│ │ ├── init.go\\n│ │ ├── link_ctx_test.go\\n│ │ ├── logs.go\\n│ │ ├── middleware.go\\n│ │ ├── simple.go\\n│ │ ├── span.go\\n│ │ └── utils.go\\n│ ├── proxy\\n│ │ ├── config.go\\n│ │ ├── example.go\\n│ │ ├── init.go\\n│ │ └── proxy_pool.go\\n│ ├── routers\\n│ │ └── router.go\\n│ ├── schema\\n│ │ ├── query\\n│ │ │ ├── merchant_query.go\\n│ │ │ ├── payfor_query.go\\n│ │ │ └── supplier_query.go\\n│ │ ├── request\\n│ │ │ ├── accountInfo.go\\n│ │ │ ├── order.go\\n│ │ │ └── order_test.go\\n│ │ └── response\\n│ │ ├── common.go\\n│ │ ├── pay_resp.go\\n│ │ └── payfor_resp.go\\n│ ├── service\\n│ │ ├── backend\\n│ │ │ ├── backend.go\\n│ │ │ └── backend_test.go\\n│ │ ├── client\\n│ │ │ ├── heepay.go\\n│ │ │ ├── models.go\\n│ │ │ ├── ocr.go\\n│ │ │ ├── ocr_test.go\\n│ │ │ └── resender.go\\n│ │ ├── message\\n│ │ │ ├── init.go\\n│ │ │ └── send_message.go\\n│ │ ├── notify\\n│ │ │ ├── order_notify.go\\n│ │ │ └── order_notify_test.go\\n│ │ ├── pay_for\\n│ │ │ ├── payfor_service.go\\n│ │ │ └── payfor_solve.go\\n│ │ ├── supplier\\n│ │ │ ├── t_mall_game\\n│ │ │ │ └── t_mall_game.go\\n│ │ │ ├── third_party\\n│ │ │ │ ├── pool\\n│ │ │ │ │ ├── card_sender\\n│ │ │ │ │ │ ├── careless.go\\n│ │ │ │ │ │ ├── careless_test.go\\n│ │ │ │ │ │ ├── eggplant.go\\n│ │ │ │ │ │ ├── eggplant_test.go\\n│ │ │ │ │ │ ├── enums.go\\n│ │ │ │ │ │ ├── fat_six.go\\n│ │ │ │ │ │ ├── fat_six_test.go\\n│ │ │ │ │ │ ├── favorable_clouds.go\\n│ │ │ │ │ │ ├── favorable_clouds_test.go\\n│ │ │ │ │ │ ├── flyfish.go\\n│ │ │ │ │ │ ├── flyfish_test.go\\n│ │ │ │ │ │ ├── flyfishv2.go\\n│ │ │ │ │ │ ├── flyfishv2_test.go\\n│ │ │ │ │ │ ├── jinke.go\\n│ │ │ │ │ │ ├── jinke_test.go\\n│ │ │ │ │ │ ├── luban.go\\n│ │ │ │ │ │ ├── luban_test.go\\n│ │ │ │ │ │ ├── magic_fish.go\\n│ │ │ │ │ │ ├── magic_fish_test.go\\n│ │ │ │ │ │ ├── models.go\\n│ │ │ │ │ │ ├── myself.go\\n│ │ │ │ │ │ ├── nuclear.go\\n│ │ │ │ │ │ ├── nuclear_test.go\\n│ │ │ │ │ │ ├── sdpay.go\\n│ │ │ │ │ │ ├── sdpay_test.go\\n│ │ │ │ │ │ ├── sesame.go\\n│ │ │ │ │ │ ├── shanfu.go\\n│ │ │ │ │ │ ├── shengtian.go\\n│ │ │ │ │ │ ├── shengtian_test.go\\n│ │ │ │ │ │ ├── up.go\\n│ │ │ │ │ │ ├── up_test.go\\n│ │ │ │ │ │ ├── wan_xin.go\\n│ │ │ │ │ │ ├── wan_xin_test.go\\n│ │ │ │ │ │ ├── wowspay.go\\n│ │ │ │ │ │ ├── wowspay_test.go\\n│ │ │ │ │ │ ├── wtr.go\\n│ │ │ │ │ │ └── wtr_test.go\\n│ │ │ │ │ ├── config.go\\n│ │ │ │ │ ├── errors.go\\n│ │ │ │ │ ├── event.go\\n│ │ │ │ │ ├── event_handlers.go\\n│ │ │ │ │ ├── events.go\\n│ │ │ │ │ ├── metrics.go\\n│ │ │ │ │ ├── models.go\\n│ │ │ │ │ ├── service.go\\n│ │ │ │ │ ├── service_test.go\\n│ │ │ │ │ ├── task.go\\n│ │ │ │ │ └── worker.go\\n│ │ │ │ ├── queue\\n│ │ │ │ │ ├── channel\\n│ │ │ │ │ │ ├── batch_six_handler.go\\n│ │ │ │ │ │ ├── channel.go\\n│ │ │ │ │ │ ├── init.go\\n│ │ │ │ │ │ └── yuhv_handler.go\\n│ │ │ │ │ ├── channel_session_test.go\\n│ │ │ │ │ ├── channel_task_handlers.go\\n│ │ │ │ │ ├── handlers.go\\n│ │ │ │ │ ├── init.go\\n│ │ │ │ │ ├── manager.go\\n│ │ │ │ │ ├── queue.go\\n│ │ │ │ │ ├── service.go\\n│ │ │ │ │ └── session.go\\n│ │ │ │ ├── aibo.go\\n│ │ │ │ ├── aibo_test.go\\n│ │ │ │ ├── apple.go\\n│ │ │ │ ├── apple_shark.go\\n│ │ │ │ ├── apple_shark_test.go\\n│ │ │ │ ├── batch_six.go\\n│ │ │ │ ├── batch_six_test.go\\n│ │ │ │ ├── c_trip_self.go\\n│ │ │ │ ├── card_type.go\\n│ │ │ │ ├── card_type_test.go\\n│ │ │ │ ├── careless.go\\n│ │ │ │ ├── careless_test.go\\n│ │ │ │ ├── daili.go\\n│ │ │ │ ├── eggplant.go\\n│ │ │ │ ├── eggplant_test.go\\n│ │ │ │ ├── fat_six.go\\n│ │ │ │ ├── fat_six_test.go\\n│ │ │ │ ├── favorable_clouds.go\\n│ │ │ │ ├── favorable_clouds_test.go\\n│ │ │ │ ├── flyfish.go\\n│ │ │ │ ├── flyfishv2.go\\n│ │ │ │ ├── heepay.go\\n│ │ │ │ ├── heepay_test.go\\n│ │ │ │ ├── init.go\\n│ │ │ │ ├── init_test.go\\n│ │ │ │ ├── jd.go\\n│ │ │ │ ├── jinke.go\\n│ │ │ │ ├── jx.go\\n│ │ │ │ ├── jx_test.go\\n│ │ │ │ ├── kuaifu.go\\n│ │ │ │ ├── luban.go\\n│ │ │ │ ├── luban_test.go\\n│ │ │ │ ├── magic_fish.go\\n│ │ │ │ ├── mf178_v2.go\\n│ │ │ │ ├── mf178_v2_test.go\\n│ │ │ │ ├── middle-open.go\\n│ │ │ │ ├── middle-open_test.go\\n│ │ │ │ ├── myself.go\\n│ │ │ │ ├── ninja.go\\n│ │ │ │ ├── ninja_test.go\\n│ │ │ │ ├── nuclear.go\\n│ │ │ │ ├── php.go\\n│ │ │ │ ├── pool.go\\n│ │ │ │ ├── qixi.go\\n│ │ │ │ ├── qixi_test.go\\n│ │ │ │ ├── scream.go\\n│ │ │ │ ├── scream_test.go\\n│ │ │ │ ├── sdpay.go\\n│ │ │ │ ├── self.go\\n│ │ │ │ ├── sesame.go\\n│ │ │ │ ├── shanfu.go\\n│ │ │ │ ├── shanfu_test.go\\n│ │ │ │ ├── shengtian.go\\n│ │ │ │ ├── star_silence.go\\n│ │ │ │ ├── star_silence_test.go\\n│ │ │ │ ├── t_mall_game.go\\n│ │ │ │ ├── trade_cat.go\\n│ │ │ │ ├── trade_cat_test.go\\n│ │ │ │ ├── up.go\\n│ │ │ │ ├── walmart.go\\n│ │ │ │ ├── walmart_self.go\\n│ │ │ │ ├── walmart_test.go\\n│ │ │ │ ├── wanxin.go\\n│ │ │ │ ├── wowspay.go\\n│ │ │ │ ├── wowspay_test.go\\n│ │ │ │ ├── wtr.go\\n│ │ │ │ ├── yuhv.go\\n│ │ │ │ └── yuhv_test.go\\n│ │ │ ├── models.go\\n│ │ │ └── supplier_interface.go\\n│ │ ├── base_service.go\\n│ │ ├── base_service_test.go\\n│ │ ├── merchant_hidden_config.go\\n│ │ ├── merchant_hidden_config_test.go\\n│ │ ├── pay_service.go\\n│ │ ├── pay_solve.go\\n│ │ ├── pay_solve_test.go\\n│ │ └── settle_service.go\\n│ ├── swagger\\n│ │ ├── swagger.json\\n│ │ └── swagger.yml\\n│ ├── tasks\\n│ │ ├── order.go\\n│ │ └── order_test.go\\n│ └── utils\\n│ ├── fingerprint\\n│ │ ├── audio.go\\n│ │ ├── canvas.go\\n│ │ ├── doc.go\\n│ │ ├── fingerprint.go\\n│ │ ├── fingerprint_test.go\\n│ │ ├── fonts.go\\n│ │ ├── screen.go\\n│ │ ├── timezone.go\\n│ │ └── webgl.go\\n│ ├── useragent\\n│ │ └── useragent.go\\n│ ├── AES_ECB.go\\n│ ├── bank.go\\n│ ├── date_time.go\\n│ ├── dm_proxy_strategy.go\\n│ ├── encryption.go\\n│ ├── md5.go\\n│ ├── proxy_pool.go\\n│ ├── proxy_pool_test.go\\n│ ├── random.go\\n│ ├── sign_verify.go\\n│ ├── sign_verify_test.go\\n│ ├── sort_go.go\\n│ └── wait.go\\n├── CLAUDE.md\\n├── build.sh\\n└── main.go\\n\"", + "current_document_structure": "WikiEncrypted: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", + "catalogue_think_content": "WikiEncrypted:sk7rVrOm0cPExtlhTWA9t2jqkuqtR+TpMJ39xEwjednHO4jCs85r/+yDsaBzcdYh8Ax6fGZtGplS1Dy8mmsBLESsHD2/y3rSQ3YLPSG5W2r69n5vfw13ywlmpqq+d8sIFpTvclg/cfIewkEsflvC7xJkF4lrO/g8nW3kgDSjD9LtbgPOMkoW8h5Q0eA1UsTw7wGp2AsKl15U3clY2Vqn/anTCZZJ0BnnoItBEBhAlfLAZEdm7qlg8YFBuqr2tquk1zDbNZQIq07XS8MMnHr0fEde9Y4vFGYir3aUKxSuIjpIwfO9KN6N3vCAfibHdn2UU2h/KtRAHKy2F1xr5L2y7YsbmsAaAR5WsqL9GsScgsnENWXVE1fzpjtRzf6uPYY8DNQ7FyYIIVwB54h6TCj3xi4eZon5uEP14tPw9sv8vFr/ZSrENi4sPS1o3pvgZiGJpnhqJzcHTE5uCGRDeKTrh3A4OUQNtnDlxkHityNisxvLGUs6AMrA++c7CIjMo+lokMVaEI114/I4zoICzlZPjiQsT9ehkPHVq1i+P7z8Kk6wQOPjwONweQTciLRnyVqd8Zpy/kGyZ8OIEfz2nUohl4J4NXnEBJaiIzMyIyjjlHgv5u0w68UxoTlwyX9RzlfUz+SLvNPo4slnL5MC/2GpFlW64v+zEkhpg25Yy3XmWW0+bC0oOvpneMxEn9dx/gYWreayg7Hk9vVg+tphRyBXbp6fkp6/96DvBXxUaAJNyet1+I/3cF64+3EoaLE0GzwXYDKITYhqE8mEcKJaQvA5ECQo5fLH3Tl7aow3HLD3qBZY/2BVwpnsY3Z32GiumBz/942A/6PSZY5kKBqgBfYQme5Aunx1Ghxfhho0EFfc+hpCZjCHyCNJkv0/3Ubuuk71BW6fRH4gZeyP3X3OYLHlqQsA2P6oelOjvJGmhhQd04qyBoyJmeDkyd/i3x/IiY/3sq/UMJw9oA5fGYzD6NxEUmdMFA86cgdeL5BAWPx6LYyhe47FgI6c3hCMbn2x1lqBv66bDxogUEu0Lh9cNsBtrstY04uJSRqPk9WmHnu4FZg3YJsQ3O5BVIs1CwZhxNCW3lkTmvmUKmbwBU1kXGdRMjcvYxp/+KNzriZ96DKeRCMSUipoZ9jmXmc546zHRbihsvrLKJAcVQ5R9GJ7l9MoU4rr+ZvaRNxNaEbVUPUJp/M6Eiuw6MNT0aVutMsA3UQE72iCCe5R2S0pC5vPAK6t87trevvHOesZMDNMVfrkvY9sTuRAFgLouMJvtaN2u4KhL1fh4cpdpIM9RNzEz8YLky0g8ZtmSrX9ik71TnuxpYWiA37/aJQsMLWuhiB+bdQP5/Z3RhEK3xdNrySRLGqueLuKQ6OwMVj4+aXPQjwFZQ669m/ULNkUx6bsa0XbzJb0yR/rnj02Vix2LD/G6MHbrWpaJ5u0bEB8os8bmKPNjV1bAMX9WVuJ/l81t0QaEdn81+UV5PTXG3+Kg2VjcIA9O21MPDkWo6WbGO71CV3YlATYLuTf/4pDfERmQjuc+Zd1vGyLh4TOktfBfH78R2J5qBKbhrhelxx6F6Iq4LGJgSCQZ3zmQoU0X28hgZrlYNOC5sSLu3aexdE5sTEh558epdgWHAcHCoxNORe2dSCC6/qecp+aq+cyHXfBZFsp6GCiijtOisQ3qESIPAIR5SYMx28ziKKbXs5UBxXX2r98Ck0fUZI1NVbolz3i5SJ9m1UQlOGPlxpsj5aItJ1sZik5DTrijtJ0GhWa/un1acLr1Q1IOhAyLtmuJu9NALt3dbXD8GNYpwZTZ1en3cYoY9ENqZKgbcOy1b4etrhRmZ6/pxTznE56l8Vc5HATXaYSLC1wKXT6lGvrhDpDoyk8Do4LAv0tn/MRmSstatsMyGwU/AUGLpV8a2YCtNS9ukPPCMYfUpmycI8ipfm4hVQjm3LgiLEzsIctJTYJiXG2F8Q/xWGHko6hquDO005isOl6hnV5W7ocLopBRhZazuEle5yiLb45QIOoEjx+X2BpKgr7ZG/JwPrhI7KBqwxFFAtz4roautgwskmXQwNCj60ALO9m6mZQhg6XC/+DOQ3zLXJjK/eoSdkvAKX7+pIr+Dn/9DSOCSfc0SRk+0a9D05MjZtzu+bVF+wPzgDFY+gqdW1xgBL7AIbiKgSJ6zsMWeafutROV+zcL4BScU00qVUQNU0WDiQnylZetG2HXweWGyUyaiBWJzpDU/6sGB9+7UKucnlpJXHYVewno6BrEfoslq0w7ApCl0cTT/QJGLgBYEJxpeKR3plVpCRtK43ZmNP0lHydvrlxyBqvpCHXra/XerRpzCHvazHWIgCv2t7DXOi0zq7RlVX6+bJAS49JSdXn/3PL660whVAxhLd7iOtAU1K5AMVB0PxtukYcb1aer7q24F6lGvieAY6xAgU73YXSxAaQ9UZcqH/SOBYNpCwph0akYt0vrKhdTPKA19PqzaGMu9gwsCrZ1BgDtzmnL5S/meAlLAne7cUwliuwOe60Wl5yjFPg+jZ5TnE0O53DJNvj1po6Uaybov8UYmfZiE9eCHH16KC4qC4k4jiH6XciVcSL/6SjiPjqdGVUCjlmpG3zAw0+N24X2OVXZ1xmjMbspZXMDPC1AqCD6oCd7WqFw2MZCamQDa+g3mDR0OSnfhyY8DQh+NrFj1fSTBlZyRKlt0IRx4H/7axbbARiEoTa1gBI5B9n/o3lXF0A3HdfSDVPn6Wbyt5uPEbCN5Ixp26GLyWz2Dr+Mir5qSAayO+DhUXOeXPY7MpI6uy/moApJcbVucwHczSXCEYA6sLiBdts9h9ncKHPFsIK29piv0rOkEePSQxJ/EUm5ffiqGyyp2ipB40OQdLw8Ljn32KjI1+LQH+lsdbRdTmPeJ1680LOWR2xLyASBsShIYz80XugbVxlnuLbyXGsn3xXNa933vDElzae31a0zx2pzGmBg3F1/RFzWguPSwffEZJ8Xj4H03gdOqAQB9azp+720WO6c7qYxAW4pxBax2Mjh63aQfEFXK5MsnTtsC+ngo9yoU0Pix1gWPnQAmsmHEMb+xU5K+tCzeWlQHhdwkL9+s4/zwZD0PacmXxd5hnRFCd47NMD+rUyFVc4u29ANxxYDmQW5xWYbxcR+o9jaMHKzX+9hd/ReVVZTUwU2a9MGRAdfI021mE7JWSWh3vxxIc/ThVDLS23mnGRHBWxDm8aqvYKxx2HhbHMUZ05mH46sNs1T4+5Gaf172Y+5x99wf3YrwRTdCFQMzCNhIM0E/Ep8vevK3dZq4xNZ84wbxZ3JX7ulDfFHxM0x7Y8s1/SHOrOJbeiROxo7L9qX5X7tu4D9OJueVCvMe5FrzZ4jlZGLj+HBArhnKiH13vNkoY8H0iKB1ZhbwxXWmkL+CIWtAk4WxY82auRCayQGJtxgrRF4nieDlaOOA4Cu8ci4cjdzCKB1pY2mGju+A9ohRkIDSDRtHUkBtix1H6eBpK+YFHHkZfHPkkAzUyafLhowEn70dG7jyyw7AlLxi3p9eaHXbhwyc6KiJpoAHGF1KVJ+/6u/ok3IxSpqo6T+8kOWqcJ6hf8ytAzITaVDADMaOXy9hyZyZyF6mPRVit0Vp3lnQXpcOZQMB0gWP/lDStgBDJZpudQ4GoTVS5kWFG66oLecUIcO8K0jER3eHgZhJQgDiIZMbOgKiB04KveO//RUq+SJfF6cjqeCBixqgtN6zqTv8IGD5F2FEVm9Shg9/aa0yIRsE6FFwVGtHgbplIUh1Gf3urOLjvbtsVuTChtcZ0XQ8TD3vJXBDknSPogqx3OHklfIGaXEyb5Ak0/UOUpktaupyUQC2WRNKVXR5SU40SG/o3JQMeuEo02j1sW3g1apK6HbD8WvukGEd/jrRycbhdgIpSHzpvOK3B8iHMd9X5Ht6OP2i0uZaDQs/66nUQwRYqIR3VvUHCM5GSwidIGA2PwQU9gzugqGx2rkdC6ZL9g0ZNQ9AIuNaa0SJsbWVvcc2Iu7R2c0UWEqfDpQiBwmg4jDE5mLSDvuunh8Nc42rCv/hpnej9HXWsnQ/7B53SWiREd/V9L/dkyVmR4x3c2KKPxhFzQl0UKnagiHh5GYS/q/mJKhDtiVCinygJ4UqaVmxs7nH1Thd7WENDip7t83tsc0AEUCl7OrC/AThCQObJYVCuI6fzTAx4LTSg9IFHoo6co2gVkM4rj12Q8cGwxYY7Ezcc5EQND5ghsfT98GbuYsQ4gfM91n4PKAQ3ja7M1NeeMP5/j9DxqSWaWyZf2ij28JX1lH1N4hQAib705lPBytovQgYW++K+RCONfV1yCL/SEkxWEWStXjT3/LdLCPs54NYmtfMohEeGOOmjFcJz2Fu9/3OaAqsufInZ44AiBZxtk7hmacTfCN3zib4Lk0Fsy2NvLoMGjzMwoD64KoJPUWkKlPv6vntRhOgkfgBXqqTFDqOGo9Jqo6BxvO4rd+ud5p84fVGB6f3ZBYy3g/1i5j2CY+FkYpLlSeq9NcArcgLsabLUQ41dcBbGQ3DnK99Q8Cb8o11tljOHPp+wtqEhAWr5m4Rj38Jg39kc7kX+d/tGV9llOWMXPDPYI+fO+KGAnrXrSZsQmEpDZjQCPX3C37eodN3sVZG/od/weEEL91CFwRA6M+5yKrYOTsipQ1VhEvKYXd6bh6AiFPk0/pTDur3dV+iNJT3Uk+9QVzHFaaWGeZ2tQ/xcJ9OxkfAJZIB/SuDIQ0Xm4M+QEbLFjZkFIc9j9ogjCHAwR1xIkhkQcQ4HTBDnh16ch8iiEYFShOKUeCdWcyU9IAe9hNwLOUEK1xGuQtVsr+9kT0BT5lBTb3dorTOK9imj3kI8sSm+e4uUCmIVPxJV6b4MWmvaNYxwYBg/KWRzMbXkBiVTMYrcFUuZk9hsuUZAOpk+OJhPEYdbj5W9jv5GfqjXzYGSbI8qp4+AY+VW6LlTAANVQ+uqEc5gcM/urgc973FhUNGTMMM3Oo8zb3laNUgfrGcLEeB2+cwSUFoBQqUl/GNcbUEkqa6heM7BxkIKLz8veN8MKnZMqYzaub2Essc6T0/lS0+a3mOGIOHNFcZ3T1eINpeBWQsvf8A4NpNSJjth2c8WUQoInVKV2kYjdF3eUZTvKZSMjIP+WiB/6glkDZX+TksIHVFGnVSns0O+PpkMJHiqKP79KfWDR82yOXr4ad4I2tyE+9ymmJEOKwWuVmqfWByJ7oWsdYyosvJ+Ig75I1be2lgiC4hYgeRr1vSpUu+oAxO3kBMbD1D3GcB9UEu2L6wtgxIDXxRU7sjkRvgNc2MYa43UCQbPdnQq9l8NXbO7FuW5YC3At5eze3oqFTdnKMs0vI9h9Wh9rzMVO31Xxcy7RH2RBlCq7/5lKTNeDeREyddX/dlTxF752jMVWHVQKHZ9+xcFe1a9SnKktGKLL4Ja+GSSUMi8gKhZX/DJe7FRct8x2z7et2jJHYGhgpOvJRkX7k2YaguPViyt4lav+gs5DpzsGB6zQbocbf8czpszTn+2rrnaFEcaMLZfi7Bv4jLjgJL6fxmXg+UHcvmgcwe8+DdUdH+qMeBbR8x3PxyUQxuEhb+D7SU7M1gm9qiWY8DTrQpTCUaHL+8Z+g/zn2NPjnnByaC1RskcksXo5AZt3mFdEixqmPnK7i5lTD7iu/yNnIjnONZpCyBXYqel/WiKbf2tKjCaIIUzLvPTDGnu04SxTt2Ksoqx3usqC84WYSALm4wO4bHtr+9f8JqcfBy0icN3gaKq9+Hxges1/6XKZiqIUr09S6ipCA3PJYUmZfmCXfJm1uVBKvmMZ91D0Sjs58cMKKx8Zcap9QBTSxhaBFMgoZPxTL98ZymzTLlBWnvlvrLe5eanfTzM7908ijeFA/hcKXzLgGz99op0xSIC9tYaDVTOTrHak6aWhENCOinI4TPaYmHJHFK9qCHCqO3OX+s7LwMAxCurbTNyptRHGVbaGF8bEPGFzkKZsiDn0IO7T/dHn9Xka+71nUxv8utSewbAQn5eFAuMeYgzCA4iyGuhwX+0eb0+6hPu6zW452OMEFrHxJVRE+uJbR32GxrAPdKMfijfYUlTgxHURndP7y58ERO9BIn1K20a1EbIK8kEk1tQDvHX2ZGMQuzUytgewXIIA+ZxWcD2bFVP7xaPzsWnQ3k0V4QkefH3No4/EcGAnoZbwymLMeh1f+Sg/3D95H6M4OLI9NCZdmxEWAo3FTBc6WaEw9V1xnzyfk+/TMcqRg50rmSpfiqbE4YiVhEoiNf3sghInsg5uY799ojNf4ZUT3hzNXCTrcEWWWGPeetutk+V0ShU4t9KvgoPbTgfA8KjZU3TrZJ9RcIpNni15Ub0fwZLN986u9xw78XnHHWdJcbDx/TSc8cx0lSEAX2x4+hhns2nMS8L1Y9qNLYD8s4z86m49+z4DEmAOmR63Isn8aGRbHguZoOUUU7RjoDUs91iWf/1tsQkr1dFySY2D95Xusa+AASQyUhgmMN82FgFgxpc0BXKuNnR/ReNTfbpiXb1qrHLXzkgkPDfl3n6MvjZPeqIxNdQ8NeIyL2GYvHjjlyiJbzrvElsGmwSeaqTmhqsPP1DBrqFWtRIQ93Qi1xrjphAOGUP02l0jjvJ+neNCbGkUwW5815ILxwNMEFtVl9yha1eXt+8OBPnkMoTRHT+y9vAN9+4VfaMPioXa7hbDpv5okB3pHwDOTmS/BP78NrJr8t3+T7KPlAtQo7v2gL+sfK9tCN2RHP2OqjHOzA+PdqW/E4UJjODsLPxe8cc3I2kUOcvuXB3XQWDpq/5GFZ6nmKbgzyDaij6n/RVxoUjV1dkmeQ7na+ZmKbi/p+TzG0DuGYv361gtMFPqXQOOBDEJkEFvry7FS3KEebqSp9WgazcwBn2edR4oNT/L0RBEdoBdJcgNXn0EHcIzY7OdC0wFOKHmZ6LuxvjxIBAY+V/y6NTqldRO/FAwtPTQS8MHzgJdqb+1s8//L21eJMEA5elq8obahImtDKUEkgveQgRPWzdjLrw1R4fUEgYFx3vkB2mBHjytbN1FrmSTA3WBPczFYEbrK6bzuWVK/PVBXwbAYNsgSy1KOhyHyLW9H7ifoRIE5ZvBwYGfqWFbzQcDglVttGO/JsFlpE52GUFhZkt1zacehhY83T3AATweN/sgBYK40094s13eunOgBlNgW72Qe0DKH6Ch2d1jjQqBed6RxbanNTGIaqVUkkMoum7QWZmYTF8I3ujF82eSv5sKFs36KGzFgIDc/z+f2mdgPI98BDyJm3qsfX2jMThAM/S0/6yh+10UgF9XtCPAOVPJ7y9ES1ktlZZPR+I9/0Bf/28/c9a2p4wa/qOKmIjL8ZSvSloQxMEebigUr8ivp9xhMeYXqgCVQ4O2It/JSafmPii+xmcvoBWP2FRP+7Xrum1X4/inMr1roxZJIoGlc/ZtBvdFs243wbOWIWt0oo+UZmm5LMHA+Nwa7sCcsKte7v/WozVZxecUZ+7sUW8x7zXuHaFeBPakViUKy7qWYIqMecFIPf7K3AX9+rfW8oZ5WypAMcBOhfYKujTkpQyqomBK80ZykGto/cyc576asjFK9y/wKdcCZmo6xNA0ffCog+COZv3sKtED+bGCXoUyLu8mTLPSPNqypz2F39dC+C/IcpllsYl4nOJQxc2EMicL3NcqVYZKJiLMJk/HnXuFnG6WBQACICbLDfZ7uAB+/AttqqCu7GRlYjPa7dWxvoEV8hpQFQUJlYGijXDbW2FgXeB9h296PS0kR04kYnP1/q7bzdNysliRE7Yo57q99KgDZoh3pZBnAGSdJTdIU34lYEwZd6boFqMQQ9n1vWzOUEblWWKNHIZFNd2UYtKViH76/Wo827o2FoFJfy0RaXU6ZPqb7eGhurxQBghCoeONlHuRx9+nDPGpRK7f2JFzzeDySNooawGZv6FleuHdgbOuEPwOAe/dJKcw9cbCri3SqBHb1wGz9ptYRE12pmlp+cPQVgWwx8vpi6ZVRiMuKebDWs99asjAJSvg3zhpOD1xBBc1HoLeWZroDLNjzi7andCW+PgEYWNk9hlrbX99wUHrc3QQLothQS7UErjwgQ3a1zrTTCqri3G6W/+dBedUc84R3Xo7KOL0yNoATb27kl7WBa0U7iL1GJcUIHCgOPI36JFFx4r/NXyWFKjnYdLKlaN+KAy6h+D+SJXQa3z7P/4U5YTPf2pyqyWoMAyaELe5pphpifnrEt5UBiBlUM/smNxWqXHFIbXX7qEemqJTWuuMqUOeNFUwQcR8pcToaWxOdgcf5Mtp7z5QZ2JdUgBxhjyGIsrD3NqjcVmGHxA7i2QHfOpbwyYQcgZap3i9aAy4PY42juEk2GnXMTlYIkSvQ9Bx8Q59hI4IcutesLjSVXQESlMEX7QTAA7aKVN4Fdo6L5VOiwT8lmhngXN6z8vn1wltH4vw3926981JyUm5EwU3MrrCwZ2uhueNeBHBNrNzYUbwkYORFBtELLX5wW3Y1WIKlFXeCyg1DEMO4POoYIHgxG/La7age4DvqDT7zCsipZpjstXzmUSQnJy7ezv7g9ZKAmZsWgWMT2c82iV2lcAsfgS8W/5+6TogdFA3/hkHwhAz7UfIFK6MyLfh8uYosn3wgdC3xGfCIXCEo25lpu2RdrTBz+qVjGmiPBgRa05CUdHbyZ078RvOjmG4LcfJvXyiDj4t2B/3jmMBqyPXHU/ezgoHsjKR8n1nhXigx4iQHhZklueNfCZ8NWm95R1mdguENswXGQcm7JLirnaMQO9J+4ywqJ7nFXLOiitRjjKlW+W98vqpuH4B/bMStoCgBtoJ8/kwLZytgNHO7wsOPR5rHnI4m3QNXhQMgb+lsRkxNKauMhrvtt7RaSL6H4s52c8y2wywHJErdWPYeVPUxID9zcvDYZsU2vv19iMKZjTane4gdUfkRJzRCcwf1mjQWImPHWrO4L5YfGK5DTf1yGR3tfiGP4Oto5Yw+ufnXrpQ6GSV/N/XBVwEa04CkDhdgbQUlEIF+kfTUCw/pZDqVpv9whVWFrkMQUAVJ582JE7fTdjhnKU6VP1WwTxHnk6m9oq3IuyrOMwkwOETEyvrPyN/TvuHoqqa4q9rUlJ6+o43no8yamIlEfHCYEPBIEIte1xSsUC2xL3QJJdYJlQbnwWZ24D3MvqVwr4pMr0N+uThTUVKfk5G2miBhStuLbkmEzgNnqv0IbRCbU7Zf7sUIabE9QikaZKveEKzKMsw43GsQKksOLZ5aU30FI/99QMtMvrxCDSFa223LOeZFhb3kGmTeP4AD7dYE0XZyJzZrlQLwMRj4XZD3aaSkUpKHTb+8TBWJzFP8B4X4b0OmSc48Pi2aK+zyklzjSSR7tu3v1Qo8UjQv8+NhD+/7ATs7olvXVOEep/b/SsDQCuWcmAPaWfq06nYxgCpLtLFoKp19QqE6CZhir+grnMppfzqqb7OdCPtlMZaeh4Y9w2yEkSbBP8D1IayjECVViSqVjGfoZ5GxRl6PdXs+PZABAOYBXZ4QptaFXP2QwEkZO1aA55devmoPp46oH6ZSI9Huxozf56W16MiuSnXhtzdyiwPBwIaofEweF8ySp1lY7E5u7DI9mYi1XuW3/GpC169ok8lRJiPdEmgUCseqWt+SAwnaAeiEAIWixVUq84V4g8c4KO5W42ic2stTpJrEMqreovM8t9Pqznfxigujkw0fpnZz8lOswGZilJVAUn+YIDpPcmrj6VAXUIGErJvIpRQj17FUEyJcyBe3L+8QtKOO8HqE2QMH32EISyFFr6zIGMDSeWCOw04BnUi3KeS1Vbx7c+PJ1qCIPszCWfN+FaE2zvkPKSigvUExPF76vs94is2Rzo3bBHj9T7lgXRFfDCCWf+3apGEJ7tSxveJZqjj6NC06yPAu/3WoPxZBrjzTkScTgR+y7w5ZPa8NUKwXPO67eanjeYsNNZgB44mKXSzOK2N5cUq0OK2wj/SbcxI/W+oUiNLetjP/ADvJJRVGW3PiGjHHmr2/ShJXOKIm5aViXBM9epavPSBZ0o=", + "recovery_checkpoint": "wiki_generation_completed", + "last_commit_id": "4a2f350946b54dea0716d3cbeb98f648050d113b", + "last_commit_update": "2025-10-07T23:59:59+08:00", + "gmt_create": "2025-08-22T10:50:23.389442+08:00", + "gmt_modified": "2025-10-08T20:18:48.9188246+08:00", + "extend_info": "{\"language\":\"zh\",\"active\":true,\"branch\":\"production\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"\"}" + } +} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index b39d8d1..48532dc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,11 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -This is a payment gateway system built with Go using the Beego framework. It handles payment processing, order management, and supplier integration for various payment methods including gift cards and other payment channels. +This is a payment gateway system built with Go using the Beego framework. It handles payment processing, order +management, and supplier integration for various payment methods including gift cards and other payment channels. ## Development Commands ### Building and Running + ```bash # Build the application ./build.sh @@ -27,6 +29,7 @@ go test ./internal/service/supplier/third_party -run TestAppleSupplier ``` ### Docker Operations + ```bash # Build Docker image docker build -f deploy/Dockerfile -t kami-gateway . @@ -45,25 +48,25 @@ docker run -p 12309:12309 \ ### Core Components 1. **Controllers** (`internal/controllers/`): HTTP request handlers - - `base_controller.go`: Base controller with common functionality - - `payfor_controller.go`: Payment processing endpoints + - `base_controller.go`: Base controller with common functionality + - `payfor_controller.go`: Payment processing endpoints 2. **Services** (`internal/service/`): Business logic layer - - `backend/`: Backend management services - - `pay_for/`: Payment processing services - - `supplier/`: Third-party supplier integrations - - `notify/`: Order notification handling + - `backend/`: Backend management services + - `pay_for/`: Payment processing services + - `supplier/`: Third-party supplier integrations + - `notify/`: Order notification handling 3. **Models** (`internal/models/`): Data models and database operations - - `order/`: Order-related models - - `merchant/`: Merchant management - - `accounts/`: Account management - - `system/`: System configuration + - `order/`: Order-related models + - `merchant/`: Merchant management + - `accounts/`: Account management + - `system/`: System configuration 4. **Supplier Integration** (`internal/service/supplier/third_party/`): - - Multiple payment supplier implementations (Apple, Walmart, etc.) - - Pool-based order processing system - - Queue-based task management + - Multiple payment supplier implementations (Apple, Walmart, etc.) + - Pool-based order processing system + - Queue-based task management ### Key Dependencies @@ -76,6 +79,7 @@ docker run -p 12309:12309 \ ### Configuration The application uses environment variables for configuration: + - `serverName`: Server identifier - `gatewayAddr`: Gateway service address - `portalAddr`: Portal service address @@ -85,6 +89,7 @@ The application uses environment variables for configuration: ### Database Schema The system uses MySQL with the following main entities: + - Orders and order settlements - Merchant accounts and configurations - Agent profit tracking @@ -93,6 +98,7 @@ The system uses MySQL with the following main entities: ### Testing The project includes unit tests for critical components: + - Supplier integration tests (`*_test.go` files) - Utility function tests - Service layer tests @@ -110,6 +116,7 @@ The project includes unit tests for critical components: ## 开发命令 ### 构建和运行 + ```bash # 构建应用程序 ./build.sh @@ -128,6 +135,7 @@ go test ./internal/service/supplier/third_party -run TestAppleSupplier ``` ### Docker 操作 + ```bash # 构建 Docker 镜像 docker build -f deploy/Dockerfile -t kami-gateway . @@ -146,25 +154,25 @@ docker run -p 12309:12309 \ ### 核心组件 1. **控制器** (`internal/controllers/`): HTTP 请求处理器 - - `base_controller.go`: 具有通用功能的基础控制器 - - `payfor_controller.go`: 支付处理端点 + - `base_controller.go`: 具有通用功能的基础控制器 + - `payfor_controller.go`: 支付处理端点 2. **服务层** (`internal/service/`): 业务逻辑层 - - `backend/`: 后台管理服务 - - `pay_for/`: 支付处理服务 - - `supplier/`: 第三方供应商集成 - - `notify/`: 订单通知处理 + - `backend/`: 后台管理服务 + - `pay_for/`: 支付处理服务 + - `supplier/`: 第三方供应商集成 + - `notify/`: 订单通知处理 3. **模型** (`internal/models/`): 数据模型和数据库操作 - - `order/`: 订单相关模型 - - `merchant/`: 商户管理 - - `accounts/`: 账户管理 - - `system/`: 系统配置 + - `order/`: 订单相关模型 + - `merchant/`: 商户管理 + - `accounts/`: 账户管理 + - `system/`: 系统配置 4. **供应商集成** (`internal/service/supplier/third_party/`): - - 多个支付供应商实现(Apple、Walmart 等) - - 基于池的订单处理系统 - - 基于队列的任务管理 + - 多个支付供应商实现(Apple、Walmart 等) + - 基于池的订单处理系统 + - 基于队列的任务管理 ### 主要依赖项 @@ -177,6 +185,7 @@ docker run -p 12309:12309 \ ### 配置 应用程序使用环境变量进行配置: + - `serverName`: 服务器标识符 - `gatewayAddr`: 网关服务地址 - `portalAddr`: 门户服务地址 @@ -186,6 +195,7 @@ docker run -p 12309:12309 \ ### 数据库架构 系统使用 MySQL,包含以下主要实体: + - 订单和订单结算 - 商户账户和配置 - 代理商利润跟踪 @@ -194,6 +204,7 @@ docker run -p 12309:12309 \ ### 测试 项目包含关键组件的单元测试: + - 供应商集成测试(`*_test.go` 文件) - 工具函数测试 - 服务层测试 \ No newline at end of file diff --git a/go.mod b/go.mod index 4b02c31..020fa30 100644 --- a/go.mod +++ b/go.mod @@ -8,16 +8,15 @@ require ( github.com/PuerkitoBio/goquery v1.10.3 github.com/beego/beego/v2 v2.3.8 github.com/bytedance/gopkg v0.1.3 - github.com/bytedance/sonic v1.14.1 + github.com/bytedance/sonic v1.14.2 github.com/dubonzi/otelresty v1.6.0 - github.com/duke-git/lancet/v2 v2.3.7 + github.com/duke-git/lancet/v2 v2.3.8 github.com/forgoer/openssl v1.8.0 github.com/go-resty/resty/v2 v2.16.5 github.com/go-sql-driver/mysql v1.9.3 github.com/go-stomp/stomp/v3 v3.1.3 github.com/google/uuid v1.6.0 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 - github.com/natefinch/lumberjack v2.0.0+incompatible github.com/prometheus/client_golang v1.23.2 github.com/redis/go-redis/v9 v9.14.0 github.com/shopspring/decimal v1.4.0 @@ -41,10 +40,9 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect - github.com/BurntSushi/toml v1.5.0 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/sonic/loader v0.4.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect @@ -79,7 +77,5 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect google.golang.org/grpc v1.75.1 // indirect google.golang.org/protobuf v1.36.9 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 11caab4..af47ca2 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= -github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= @@ -16,10 +14,10 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= -github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w= -github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc= -github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= +github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= +github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -33,8 +31,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dubonzi/otelresty v1.6.0 h1:Oi9fY9bj3/J5R9+FZVMOk+10HtLs6S57fy8nQY5X3C0= github.com/dubonzi/otelresty v1.6.0/go.mod h1:H+lNImIXAOhK4bk2bZBPDDdp5xGYvtnrUX8F8uVNE30= -github.com/duke-git/lancet/v2 v2.3.7 h1:nnNBA9KyoqwbPm4nFmEFVIbXeAmpqf6IDCH45+HHHNs= -github.com/duke-git/lancet/v2 v2.3.7/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc= +github.com/duke-git/lancet/v2 v2.3.8 h1:dlkqn6Nj2LRWFuObNxttkMHxrFeaV6T26JR8jbEVbPg= +github.com/duke-git/lancet/v2 v2.3.8/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc= github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw= github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -88,8 +86,6 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= -github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= @@ -111,9 +107,11 @@ github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+D github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= @@ -269,10 +267,6 @@ google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXn gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/routers/router.go b/internal/routers/router.go index fdf177a..6508958 100644 --- a/internal/routers/router.go +++ b/internal/routers/router.go @@ -73,4 +73,5 @@ func init() { web.Router("/careless/notify", &third_party.CarelessImpl{}, "*:PayNotify") web.Router("/nuclear/notify", &third_party.NuclearImpl{}, "*:PayNotify") web.Router("/origin/notify", &third_party.OriginImpl{}, "*:PayNotify") + web.Router("/lianIns/notify", &third_party.LianInsImpl{}, "*:PayNotify") } diff --git a/internal/service/supplier/third_party/init.go b/internal/service/supplier/third_party/init.go index b30054c..e362904 100644 --- a/internal/service/supplier/third_party/init.go +++ b/internal/service/supplier/third_party/init.go @@ -60,6 +60,7 @@ var supplierCode2Name = map[string]string{ "NUCLEAR": "玖隆核销平台", "SDPAY": "闪电核销平台", "ORIGIN": "山禾", + "LIANINS": "燕子核销平台", } var registerSupplier = make(map[string]supplier.PayInterface) @@ -150,6 +151,8 @@ func init() { logs.Notice(CheckSupplierByCode("UP")) registerSupplier["ORIGIN"] = new(OriginImpl) logs.Notice(CheckSupplierByCode("ORIGIN")) + registerSupplier["LIANINS"] = new(LianInsImpl) + logs.Notice(CheckSupplierByCode("LIANINS")) } func GetPaySupplierByCode(code string) supplier.PayInterface { diff --git a/internal/service/supplier/third_party/lian_ins.go b/internal/service/supplier/third_party/lian_ins.go new file mode 100644 index 0000000..23a3c42 --- /dev/null +++ b/internal/service/supplier/third_party/lian_ins.go @@ -0,0 +1,286 @@ +package third_party + +import ( + "context" + "encoding/json" + "gateway/internal/config" + "gateway/internal/models/merchant" + "gateway/internal/models/merchant_deploy" + "gateway/internal/models/order" + "gateway/internal/models/payfor" + "gateway/internal/models/road" + "gateway/internal/models/supply_model" + "gateway/internal/otelTrace" + "gateway/internal/service" + "gateway/internal/service/client" + "gateway/internal/service/supplier" + "gateway/internal/service/supplier/third_party/pool/card_sender" + "strconv" + + "github.com/beego/beego/v2/client/httplib" + "github.com/duke-git/lancet/v2/convertor" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" + + "github.com/beego/beego/v2/server/web" + "github.com/widuu/gojson" +) + +type LianInsImpl struct { + web.Controller +} + +// HasDependencyHTML 是否有单独的支付页面 +func (c *LianInsImpl) HasDependencyHTML() bool { + return false +} + +func (c *LianInsImpl) SendCard(ctx context.Context, jsonStr string, cardInfo supplier.RedeemCardInfo, attach string, merchantInfo merchant.MerchantInfo, roadInfo road.RoadInfo) (bool, string) { + orderAmount, _ := (&cardTypeQuery{ + OrderNo: attach, + QueryType: gojson.Json(roadInfo.Params).Get("queryType").Tostring(), + CardNo: cardInfo.CardNo, + CardPwd: cardInfo.Data, + Balance: cardInfo.GetFaceTypeFloat(ctx), + }).GetBalance(ctx) + cardInfo.FaceType = strconv.FormatFloat(orderAmount, 'f', 2, 64) + otelTrace.Logger.WithContext(ctx).Info("获取订单金额", zap.Any("orderAmount", cardInfo)) + merchantDeploy := merchant_deploy.GetMerchantDeployByUidAndRoadUid(ctx, merchantInfo.MerchantUid, roadInfo.RoadUid) + if merchantDeploy.MerchantUid == "" { + return false, "商户不存在" + } + if merchantDeploy.SubmitStrategy == merchant_deploy.SUBMIT_STRATEGY_POOL { + if err := orderPoolService.PushOrder(ctx, card_sender.SendCardTask{ + CardInfo: cardInfo, + RoadUid: roadInfo.RoadUid, + LocalOrderID: attach, + SendCardTaskType: card_sender.SendCardTaskTypeEnumLianIns, + NeedQuery: gojson.Json(roadInfo.Params).Get("needQuery").Tostring() == "1", + }); err != nil { + return false, err.Error() + } + return true, "订单已提交" + } + if err := orderPoolService.SubmitOrder(ctx, card_sender.SendCardTask{ + CardInfo: cardInfo, + RoadUid: roadInfo.RoadUid, + LocalOrderID: attach, + SendCardTaskType: card_sender.SendCardTaskTypeEnumLianIns, + NeedQuery: gojson.Json(roadInfo.Params).Get("needQuery").Tostring() == "1", + }); err != nil { + return false, err.Error() + } + return true, "订单已提交" +} + +func (c *LianInsImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData { + ctx, span := otelTrace.Span(ctx, "LianInsImpl", "LianInsImpl.Scan", trace.WithAttributes( + attribute.String("bankOrderId", orderInfo.BankOrderId), + attribute.String("merchantUid", orderInfo.MerchantUid), + )) + defer span.End() + + cdata := supplier.RedeemCardInfo{} + err := json.Unmarshal([]byte(orderInfo.ExValue), &cdata) + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("格式化数据失败", zap.String("ExValue", orderInfo.ExValue)) + return supplier.ScanData{Status: "-1", Msg: "订单有误,请稍后再试"} + } + + ok, str := c.SendCard(ctx, roadInfo.Params, cdata, orderInfo.BankOrderId, merchantInfo, roadInfo) + var scanData supplier.ScanData + if !ok { + scanData = supplier.ScanData{ + Status: "-1", + Msg: "失败:" + str, + BankNo: orderInfo.MerchantOrderId, + OrderNo: orderInfo.BankOrderId, + ReturnData: str, + } + return scanData + } + scanData.Status = "00" + scanData.OrderNo = orderInfo.BankOrderId + scanData.BankNo = orderInfo.MerchantOrderId + scanData.OrderPrice = strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64) + scanData.ReturnData = str + return scanData +} + +func (c *LianInsImpl) PayNotify() { + ctx := c.Ctx.Request.Context() + + req := struct { + OrderNo string `json:"order_no"` + TradeNo string `json:"trade_no"` + Amount string `json:"amount"` + MerchantNo string `json:"merchant_no"` + Status int `json:"status"` + ApiKey string `json:"api_key"` + }{} + if err := c.Bind(&req); err != nil { + otelTrace.Logger.WithContext(ctx).Error("参数错误", zap.Error(err)) + c.Ctx.WriteString("参数错误") + return + } + if req.Status == 2 { + c.Ctx.WriteString("处理中的订单不要回调!!!") + return + } + otelTrace.Logger.WithContext(ctx).Info("回调通知", zap.Any("req", req)) + localId, err := orderPoolService.GetLocalIdByOrderId(ctx, req.TradeNo) + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("获取本地订单ID失败", zap.Error(err)) + c.Ctx.WriteString("fail") + return + } + + orderInfo := order.GetOrderByBankOrderId(ctx, localId) + + if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 { + otelTrace.Logger.WithContext(ctx).Error("回调的订单号不存在,订单号", zap.String("tradeNo", req.TradeNo)) + c.Ctx.WriteString("fail") + return + } + + if orderInfo.Status != "wait" { + otelTrace.Logger.WithContext(ctx).Info("订单已经回调,不进行回调") + c.Ctx.WriteString("success") + return + } + + roadInfo := road.GetRoadInfoByRoadUid(ctx, orderInfo.RoadUid) + if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 { + otelTrace.Logger.WithContext(ctx).Error("支付通道已经关系或者删除,不进行回调") + c.Ctx.WriteString("fail") + return + } + + price, err := strconv.ParseFloat(req.Amount, 64) + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("金额转换失败", zap.Error(err)) + c.Ctx.WriteString("fail") + return + } + if req.Status == 1 { + isOk := false + if price == orderInfo.OrderAmount { + isOk = service.SolvePaySuccess(ctx, orderInfo.BankOrderId, orderInfo.OrderAmount, orderInfo.MerchantUid, "支付成功") + } else { + SolvePaySuccessByAmountDifferent(ctx, orderInfo.BankOrderId, price, orderInfo.BankOrderId, convertor.ToString(req)) + } + if isOk { + c.Ctx.WriteString("success") + } else { + c.Ctx.WriteString("fail") + } + } else { + cdata := supplier.RedeemCardInfo{} + _ = json.Unmarshal([]byte(orderInfo.ExValue), &cdata) + if gojson.Json(roadInfo.Params).Get("jvnkaQuery").Tostring() == "1" { + _, _ = client.NewHeePayClient().ToString(ctx, &client.QueryCardInput{ + OrderNo: orderInfo.BankOrderId, + CardNo: cdata.CardNo, + CardPassword: cdata.Data, + }) + } + isOk := service.SolvePayFail(ctx, orderInfo.BankOrderId, orderInfo.BankOrderId, "支付失败") + if isOk { + c.Ctx.WriteString("success") + } else { + c.Ctx.WriteString("fail") + } + } +} + +func (c *LianInsImpl) PayQuery(orderInfo order.OrderInfo, roadInfo road.RoadInfo) bool { + return false +} + +func (c *LianInsImpl) PayQueryV2(orderInfo order.OrderInfo, roadInfo road.RoadInfo) supply_model.MsgModel { + return supply_model.RemoteDataErr +} + +func (c *LianInsImpl) PayFor(info payfor.PayforInfo) string { + return "" +} + +func (c *LianInsImpl) PayForQuery(payFor payfor.PayforInfo) (string, string) { + cfg := config.Config{} + url1, err := cfg.GetMFCardQueryUrl() + if err != nil { + return config.PAYFOR_FAIL, "" + } + ctx := context.Background() + params := map[string]string{} + params["order_id"] = payFor.BankOrderId + params["app_key"] = gojson.Json("").Get("appKey").Tostring() + + req := httplib.Post(url1) + marshal, err := json.Marshal(params) + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("Map转化为byte数组失败,异常。", zap.Error(err)) + return config.PAYFOR_FAIL, "内部错误请稍后再试试" + } + otelTrace.Logger.WithContext(ctx).Info("请求参数" + string(marshal)) + req.Header("Content-Type", "application/json") + req.Body(marshal) + req.Header("Accept-Charset", "utf-8") + + response, err := req.String() + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("MF GetToken 请求失败:", zap.Error(err)) + return config.PAYFOR_FAIL, "" + } + + otelTrace.Logger.WithContext(ctx).Info("远端请求返回数据", zap.String("response", response)) + + if gojson.Json(response).Get("code").Tostring() == "" { + otelTrace.Logger.WithContext(ctx).Error("远程调用失败") + return config.PAYFOR_BANKING, "" + } + + if gojson.Json(response).Get("code").Tostring() == "0" { + type data struct { + OrderID int64 `json:"order_id"` + CardNo string `json:"card_no"` + CardPwd string `json:"card_pwd"` + Status int `json:"status"` + RspInfo string `json:"rsp_info"` + FaceVal int `json:"face_val"` + Amount int `json:"amount"` + Discount string `json:"discount"` + } + + var d data + + err2 := json.Unmarshal([]byte(gojson.Json(response).Get("data").Tostring()), &d) + if err2 != nil { + return config.PAYFOR_FAIL, "" + } + + if d.Status == 9 { + return config.PAYFOR_SUCCESS, "" + } + + if d.Status == 4 { + return config.PAYFOR_BANKING, "" + } + + if d.Status == 7 || d.Status == 8 { + return config.PAYFOR_FAIL, "" + } + } + + otelTrace.Logger.WithContext(ctx).Error("远程调用失败") + return config.PAYFOR_BANKING, "" +} + +func (c *LianInsImpl) BalanceQuery(roadInfo road.RoadInfo) float64 { + return 0.00 +} + +func (c *LianInsImpl) PayForNotify() string { + return "" +} diff --git a/internal/service/supplier/third_party/pool/card_sender/enums.go b/internal/service/supplier/third_party/pool/card_sender/enums.go index 2e652b3..124d1b0 100644 --- a/internal/service/supplier/third_party/pool/card_sender/enums.go +++ b/internal/service/supplier/third_party/pool/card_sender/enums.go @@ -46,6 +46,7 @@ const ( SendCardTaskTypeEnumNuclear SendCardTaskEnum = "NUCLEAR" SendCardTaskTypeEnumSdPay SendCardTaskEnum = "SDPAY" SendCardTaskTypeEnumOrigin SendCardTaskEnum = "ORIGIN" + SendCardTaskTypeEnumLianIns SendCardTaskEnum = "LIANINS" ) func GetAllSendCardTaskType() []SendCardTaskEnum { @@ -71,6 +72,7 @@ func GetAllSendCardTaskType() []SendCardTaskEnum { SendCardTaskTypeEnumNuclear, SendCardTaskTypeEnumSdPay, SendCardTaskTypeEnumOrigin, + SendCardTaskTypeEnumLianIns, } } @@ -120,6 +122,8 @@ func (sendCardTaskTypeEnum SendCardTaskEnum) GetSendCardTaskType() sendCardTaskT return &SendCardTaskTypeNuclear{} case SendCardTaskTypeEnumOrigin: return &SendCardTaskTypeOrigin{} + case SendCardTaskTypeEnumLianIns: + return &SendCardTaskTypeLianIns{} } return nil } diff --git a/internal/service/supplier/third_party/pool/card_sender/lianins.go b/internal/service/supplier/third_party/pool/card_sender/lianins.go new file mode 100644 index 0000000..3cb7126 --- /dev/null +++ b/internal/service/supplier/third_party/pool/card_sender/lianins.go @@ -0,0 +1,166 @@ +package card_sender + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "gateway/internal/config" + "gateway/internal/models/road" + "gateway/internal/otelTrace" + "gateway/internal/utils" + "github.com/bytedance/sonic" + "net/url" + "sort" + "strings" + "time" + + "github.com/dubonzi/otelresty" + "github.com/duke-git/lancet/v2/convertor" + "github.com/duke-git/lancet/v2/maputil" + "github.com/duke-git/lancet/v2/pointer" + "github.com/go-resty/resty/v2" + "github.com/widuu/gojson" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" +) + +type SendCardTaskTypeLianIns struct { + sendCardTaskTypeSendCardTaskBase +} + +func (s *SendCardTaskTypeLianIns) CreateOrder(ctx context.Context, roadUid string, faceValue float64) (OrderPoolItem, error) { + orderPoolItem := OrderPoolItem{} + roadInfo := road.GetRoadInfoByRoadUid(ctx, roadUid) + orderId := utils.GenerateId() + reqBody := struct { + Amount string `json:"amount"` + MerNo string `json:"mer_no"` + TradeNo string `json:"trade_no"` + NotifyUrl string `json:"notify_url"` + ReturnUrl string `json:"return_url"` + ApiKey string `json:"api_key"` + ChannelId string `json:"channel_id"` + }{ + Amount: fmt.Sprintf("%.0f", faceValue), + MerNo: orderId, + TradeNo: utils.GenerateId(), + NotifyUrl: config.GetConfig().GatewayAddr() + "/lianIns/notify", + ReturnUrl: "https://baidu.com", + ApiKey: gojson.Json(roadInfo.Params).Get("api_key").Tostring(), + ChannelId: gojson.Json(roadInfo.Params).Get("channel_id").Tostring(), + } + webClient := resty.New().SetTimeout(time.Second * 10).SetRetryCount(3) + otelresty.TraceClient(webClient) + response, err := webClient.R().SetBody(reqBody).Post("https://pay.lianins.top/openapi/sub_order") + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("请求订单失败", zap.Error(err)) + return orderPoolItem, err + } + respData := struct { + Code int `json:"code"` + Status string `json:"status"` + Message string `json:"message"` + Data struct { + OrderNo string `json:"order_no"` + TradeNo string `json:"trade_no"` + MerchantNo string `json:"merchant_no"` + Amount string `json:"amount"` + Remark string `json:"remark"` + PayUrl string `json:"pay_url"` + Status int `json:"status"` + VerifyStatus int `json:"verify_status"` + } `json:"data,omitempty"` + }{} + if err = json.Unmarshal(response.Body(), &respData); err != nil { + otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err)) + return orderPoolItem, err + } + orderPoolItem = OrderPoolItem{ + OrderID: orderId, + PayURL: respData.Data.PayUrl, + RoadUid: roadUid, + CreateTime: time.Now(), + FaceValue: faceValue, + DispatchCount: 0, + SendCardTaskType: SendCardTaskTypeEnumLianIns, + } + return orderPoolItem, nil +} + +func (s *SendCardTaskTypeLianIns) channelOne(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error { + webClient := resty.New().SetTimeout(time.Second * 30).SetRetryCount(3) + otelresty.TraceClient(webClient) + payUrl, err := url.Parse(orderItem.PayURL) + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err)) + return errors.New("解析提交地址失败") + } + + reqBody := struct { + TradeNo string `json:"trade_no"` + CardNo string `json:"card_no"` + CardPwd string `json:"card_pwd"` + }{ + TradeNo: payUrl.Query().Get("trade_no"), + CardPwd: task.CardInfo.Data, + CardNo: task.CardInfo.CardNo, + } + + response, err := webClient.R().SetBody(reqBody).Post("https://api.gjifu.cn/openapi/order/sub") + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("请求失败", zap.Error(err)) + return err + } + + respData := struct { + Code int `json:"code"` + Status string `json:"status"` + Message string `json:"message"` + }{} + otelTrace.Logger.WithContext(ctx).Info("请求结果", zap.Any("response", response.String())) + err = sonic.Unmarshal(response.Body(), &respData) + if err != nil { + otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err)) + return err + } + if respData.Code != 1000 { + otelTrace.Logger.WithContext(ctx).Error("提交失败") + return errors.New(respData.Message) + } + return nil +} + +func (s *SendCardTaskTypeLianIns) HandleSendCardTask(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error { + ctx, span := otelTrace.Span(ctx, "SendCardTaskTypeLuban", "SendCardTaskTypeLuban.HandleSendCardTask", trace.WithAttributes( + attribute.String("bankOrderId", task.LocalOrderID), + attribute.String("cardNo", task.CardInfo.CardNo), + attribute.String("cardPassword", task.CardInfo.Data), + attribute.String("orderId", orderItem.OrderID), + )) + defer span.End() + if strings.Contains(orderItem.PayURL, "api.xxsbm.com") { + err2 := (&SendCardTaskTypeFatSix{}).HandleSendCardTask(ctx, orderItem, task) + return err2 + } + return s.channelOne(ctx, orderItem, task) +} + +func (s *SendCardTaskTypeLianIns) sign(ctx context.Context, params map[string]any, key string) string { + keys := maputil.Keys(params) + sort.Strings(keys) + signD := "" + for _, subKey := range keys { + if pointer.IsNil(params[subKey]) || convertor.ToString(params[subKey]) == "" { + continue + } + signD += subKey + "=" + convertor.ToString(params[subKey]) + "&" + } + signD += "key=" + key + return strings.ToUpper(utils.EncodeMd5Str(signD)) +} + +func (s *SendCardTaskTypeLianIns) QueryOrder(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error { + return nil +} diff --git a/internal/service/supplier/third_party/pool/card_sender/lianins_test.go b/internal/service/supplier/third_party/pool/card_sender/lianins_test.go new file mode 100644 index 0000000..6f41568 --- /dev/null +++ b/internal/service/supplier/third_party/pool/card_sender/lianins_test.go @@ -0,0 +1,55 @@ +package card_sender + +import ( + "encoding/json" + "gateway/internal/utils" + "github.com/dubonzi/otelresty" + "github.com/go-resty/resty/v2" + "testing" + "time" +) + +func TestSendCardTaskTypeLianIns_CreateOrder(t *testing.T) { + reqBody := struct { + Amount string `json:"amount"` + MerNo string `json:"mer_no"` + TradeNo string `json:"trade_no"` + NotifyUrl string `json:"notify_url"` + ReturnUrl string `json:"return_url"` + ApiKey string `json:"api_key"` + ChannelId string `json:"channel_id"` + }{ + Amount: "10", + MerNo: "860078486326972834222944", + TradeNo: utils.GenerateId(), + NotifyUrl: "https://baidu.com", + ReturnUrl: "https://baidu.com", + ApiKey: "7XoWOExJxytVCfNTGxfFNoeIqo4OT2fO", + ChannelId: "888", + } + webClient := resty.New().SetTimeout(time.Second * 10).SetRetryCount(3) + otelresty.TraceClient(webClient) + response, err := webClient.R().SetBody(reqBody).Post("https://pay.lianins.top/openapi/sub_order") + if err != nil { + t.Error(err) + } + respData := struct { + Code int `json:"code"` + Status string `json:"status"` + Message string `json:"message"` + Data struct { + OrderNo string `json:"order_no"` + TradeNo string `json:"trade_no"` + MerchantNo string `json:"merchant_no"` + Amount string `json:"amount"` + Remark string `json:"remark"` + PayUrl string `json:"pay_url"` + Status int `json:"status"` + VerifyStatus int `json:"verify_status"` + } `json:"data,omitempty"` + }{} + if err = json.Unmarshal(response.Body(), &respData); err != nil { + t.Error(err) + } + t.Log(respData) +}