From b8dda7e62a2fb84af3d28ada0801f16caa1c4e8a Mon Sep 17 00:00:00 2001 From: huang Date: Sat, 31 Jan 2026 12:15:12 +0800 Subject: [PATCH] =?UTF-8?q?chore(bootstrap):=20=E6=9B=B4=E6=96=B0=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E6=B3=A8=E5=85=A5=E5=92=8C=20API=20=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bootstrap 注册 RechargeHandler 和 RechargeService - Bootstrap 注册 RechargeStore 数据访问层 - 更新 PaymentCallback 依赖注入(添加 RechargeService) - 更新 OpenAPI 文档生成器注册充值接口 - 同步 admin-openapi.yaml 文档(新增充值和代购预检接口) --- docs/admin-openapi.yaml | 871 ++++++++++++++++++++++++++++++++- internal/bootstrap/handlers.go | 3 +- internal/bootstrap/services.go | 3 + internal/bootstrap/stores.go | 2 + internal/bootstrap/types.go | 1 + pkg/openapi/handlers.go | 3 +- 6 files changed, 875 insertions(+), 8 deletions(-) diff --git a/docs/admin-openapi.yaml b/docs/admin-openapi.yaml index 1f7dbbc..f516351 100644 --- a/docs/admin-openapi.yaml +++ b/docs/admin-openapi.yaml @@ -1,10 +1,5 @@ components: schemas: - AppBindWechatRequest: - properties: - code: - type: string - type: object AppLoginRequest: properties: code: @@ -1222,6 +1217,22 @@ components: - perm_code - perm_type type: object + DtoCreateRechargeRequest: + properties: + amount: + description: 充值金额(分) + type: integer + payment_method: + description: 支付方式 + type: string + resource_id: + description: 资源ID + minimum: 0 + type: integer + resource_type: + description: 资源类型 + type: string + type: object DtoCreateRoleRequest: properties: role_desc: @@ -2441,9 +2452,22 @@ components: properties: access_token: type: string + buttons: + description: 按钮权限码 + items: + type: string + nullable: true + type: array expires_in: type: integer + menus: + description: 菜单树 + items: + $ref: '#/components/schemas/DtoMenuNode' + nullable: true + type: array permissions: + description: 所有权限码(向后兼容) items: type: string nullable: true @@ -2453,6 +2477,31 @@ components: user: $ref: '#/components/schemas/DtoUserInfo' type: object + DtoMenuNode: + properties: + children: + description: 子菜单 + items: + $ref: '#/components/schemas/DtoMenuNode' + nullable: true + type: array + id: + description: 权限ID + minimum: 0 + type: integer + name: + description: 菜单名称 + type: string + perm_code: + description: 权限码 + type: string + sort: + description: 排序值 + type: integer + url: + description: 路由路径 + type: string + type: object DtoMyCommissionRecordItem: properties: amount: @@ -2934,6 +2983,37 @@ components: description: 请求路径 type: string type: object + DtoPersonalCustomerResponse: + properties: + avatar_url: + description: 头像URL + type: string + created_at: + description: 创建时间 + type: string + id: + description: 客户ID + minimum: 0 + type: integer + nickname: + description: 昵称 + type: string + phone: + description: 手机号 + type: string + status: + description: 状态 (0:禁用, 1:启用) + type: integer + updated_at: + description: 更新时间 + type: string + wx_open_id: + description: 微信OpenID + type: string + wx_union_id: + description: 微信UnionID + type: string + type: object DtoPriceAdjustment: properties: type: @@ -2946,6 +3026,50 @@ components: - type - value type: object + DtoPurchaseCheckRequest: + properties: + order_type: + description: 订单类型 (single_card:单卡购买, device:设备购买) + type: string + package_ids: + description: 套餐ID列表 + items: + minimum: 0 + type: integer + maxItems: 10 + minItems: 1 + nullable: true + type: array + resource_id: + description: 资源ID (IoT卡ID或设备ID) + minimum: 0 + type: integer + required: + - order_type + - resource_id + - package_ids + type: object + DtoPurchaseCheckResponse: + properties: + actual_payment: + description: 实际支付金额(分) + type: integer + force_recharge_amount: + description: 强充金额(分) + type: integer + message: + description: 提示信息 + type: string + need_force_recharge: + description: 是否需要强充 + type: boolean + total_package_amount: + description: 套餐总价(分) + type: integer + wallet_credit: + description: 钱包到账金额(分) + type: integer + type: object DtoRecallCardsReq: properties: iccids: @@ -3119,6 +3243,113 @@ components: nullable: true type: array type: object + DtoRechargeCheckResponse: + properties: + current_accumulated: + description: 当前累计充值金额(分) + type: integer + first_commission_paid: + description: 一次性佣金是否已发放 + type: boolean + force_recharge_amount: + description: 强充金额(分) + type: integer + max_amount: + description: 最大充值金额(分) + type: integer + message: + description: 提示信息 + type: string + min_amount: + description: 最小充值金额(分) + type: integer + need_force_recharge: + description: 是否需要强充 + type: boolean + threshold: + description: 佣金触发阈值(分) + type: integer + trigger_type: + description: 触发类型 + type: string + type: object + DtoRechargeListResponse: + properties: + list: + description: 列表数据 + items: + $ref: '#/components/schemas/DtoRechargeResponse' + nullable: true + type: array + page: + description: 当前页码 + type: integer + page_size: + description: 每页数量 + type: integer + total: + description: 总记录数 + type: integer + total_pages: + description: 总页数 + type: integer + type: object + DtoRechargeResponse: + properties: + amount: + description: 充值金额(分) + type: integer + completed_at: + description: 完成时间 + format: date-time + nullable: true + type: string + created_at: + description: 创建时间 + format: date-time + type: string + id: + description: 充值订单ID + minimum: 0 + type: integer + paid_at: + description: 支付时间 + format: date-time + nullable: true + type: string + payment_channel: + description: 支付渠道 + nullable: true + type: string + payment_method: + description: 支付方式 + type: string + payment_transaction_id: + description: 第三方支付交易号 + nullable: true + type: string + recharge_no: + description: 充值订单号 + type: string + status: + description: 充值状态 + type: integer + status_text: + description: 状态文本 + type: string + updated_at: + description: 更新时间 + format: date-time + type: string + user_id: + description: 用户ID + minimum: 0 + type: integer + wallet_id: + description: 钱包ID + minimum: 0 + type: integer + type: object DtoRefreshTokenRequest: properties: refresh_token: @@ -4224,6 +4455,73 @@ components: description: 用户名 type: string type: object + DtoWechatH5Detail: + properties: + type: + description: 场景类型 (iOS:苹果, Android:安卓, Wap:浏览器) + type: string + type: object + DtoWechatH5SceneInfo: + properties: + h5_info: + $ref: '#/components/schemas/DtoWechatH5Detail' + payer_client_ip: + description: 用户终端IP + type: string + required: + - payer_client_ip + type: object + DtoWechatOAuthRequest: + properties: + code: + description: 微信授权码 + type: string + required: + - code + type: object + DtoWechatOAuthResponse: + properties: + access_token: + description: 访问令牌 + type: string + customer: + $ref: '#/components/schemas/DtoPersonalCustomerResponse' + expires_in: + description: 令牌有效期(秒) + type: integer + type: object + DtoWechatPayH5Params: + properties: + scene_info: + $ref: '#/components/schemas/DtoWechatH5SceneInfo' + required: + - scene_info + type: object + DtoWechatPayH5Response: + properties: + h5_url: + description: 微信支付跳转URL + type: string + type: object + DtoWechatPayJSAPIParams: + properties: + openid: + description: 用户OpenID + type: string + required: + - openid + type: object + DtoWechatPayJSAPIResponse: + properties: + pay_config: + additionalProperties: {} + description: JSSDK支付配置 + nullable: true + type: object + prepay_id: + description: 预支付交易会话标识 + type: string + type: object DtoWithdrawalApprovalResp: properties: id: @@ -10107,6 +10405,69 @@ paths: summary: 取消订单 tags: - 订单管理 + /api/admin/orders/purchase-check: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DtoPurchaseCheckRequest' + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoPurchaseCheckResponse' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 未认证或认证已过期 + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 无权访问 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + security: + - BearerAuth: [] + summary: 套餐购买预检 + tags: + - 订单管理 /api/admin/package-series: get: parameters: @@ -14547,7 +14908,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AppBindWechatRequest' + $ref: '#/components/schemas/DtoWechatOAuthRequest' responses: "400": content: @@ -14748,6 +15109,56 @@ paths: summary: 更新个人资料 tags: - 个人客户 - 账户 + /api/c/v1/wechat/auth: + post: + description: 使用微信授权码登录,自动创建或关联用户 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DtoWechatOAuthRequest' + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoWechatOAuthResponse' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + summary: 微信授权登录 + tags: + - 个人客户 - 认证 /api/callback/alipay: post: responses: @@ -15509,6 +15920,150 @@ paths: summary: 钱包支付 tags: - H5 订单 + /api/h5/orders/{id}/wechat-pay/h5: + post: + parameters: + - description: 订单ID + in: path + name: id + required: true + schema: + description: 订单ID + minimum: 0 + type: integer + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DtoWechatPayH5Params' + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoWechatPayH5Response' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 未认证或认证已过期 + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 无权访问 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + security: + - BearerAuth: [] + summary: 微信 H5 支付 + tags: + - H5 订单 + /api/h5/orders/{id}/wechat-pay/jsapi: + post: + parameters: + - description: 订单ID + in: path + name: id + required: true + schema: + description: 订单ID + minimum: 0 + type: integer + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DtoWechatPayJSAPIParams' + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoWechatPayJSAPIResponse' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 未认证或认证已过期 + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 无权访问 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + security: + - BearerAuth: [] + summary: 微信 JSAPI 支付 + tags: + - H5 订单 /api/h5/password: put: requestBody: @@ -15595,6 +16150,310 @@ paths: summary: 刷新 Token tags: - H5 认证 + /api/h5/wallets/recharge: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DtoCreateRechargeRequest' + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoRechargeResponse' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 未认证或认证已过期 + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 无权访问 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + security: + - BearerAuth: [] + summary: 创建充值订单 + tags: + - H5 充值 + /api/h5/wallets/recharge-check: + get: + parameters: + - description: 资源类型 + in: query + name: resource_type + schema: + description: 资源类型 + type: string + - description: 资源ID + in: query + name: resource_id + schema: + description: 资源ID + minimum: 0 + type: integer + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoRechargeCheckResponse' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 未认证或认证已过期 + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 无权访问 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + security: + - BearerAuth: [] + summary: 充值预检 + tags: + - H5 充值 + /api/h5/wallets/recharges: + get: + parameters: + - description: 页码 + in: query + name: page + schema: + description: 页码 + type: integer + - description: 每页数量 + in: query + name: page_size + schema: + description: 每页数量 + type: integer + - description: 钱包ID + in: query + name: wallet_id + schema: + description: 钱包ID + minimum: 0 + nullable: true + type: integer + - description: 状态 + in: query + name: status + schema: + description: 状态 + nullable: true + type: integer + - description: 开始时间 + in: query + name: start_time + schema: + description: 开始时间 + format: date-time + nullable: true + type: string + - description: 结束时间 + in: query + name: end_time + schema: + description: 结束时间 + format: date-time + nullable: true + type: string + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoRechargeListResponse' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 未认证或认证已过期 + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 无权访问 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + security: + - BearerAuth: [] + summary: 获取充值订单列表 + tags: + - H5 充值 + /api/h5/wallets/recharges/{id}: + get: + parameters: + - description: 充值订单ID + in: path + name: id + required: true + schema: + description: 充值订单ID + minimum: 0 + type: integer + responses: + "200": + content: + application/json: + schema: + properties: + code: + description: 响应码 + example: 0 + type: integer + data: + $ref: '#/components/schemas/DtoRechargeResponse' + msg: + description: 响应消息 + example: success + type: string + timestamp: + description: 时间戳 + format: date-time + type: string + required: + - code + - msg + - data + - timestamp + type: object + description: 成功 + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 请求参数错误 + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 未认证或认证已过期 + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 无权访问 + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + description: 服务器内部错误 + security: + - BearerAuth: [] + summary: 获取充值订单详情 + tags: + - H5 充值 /health: get: responses: diff --git a/internal/bootstrap/handlers.go b/internal/bootstrap/handlers.go index ff7c440..f9f938d 100644 --- a/internal/bootstrap/handlers.go +++ b/internal/bootstrap/handlers.go @@ -45,6 +45,7 @@ func initHandlers(svc *services, deps *Dependencies) *Handlers { ShopPackageBatchPricing: admin.NewShopPackageBatchPricingHandler(svc.ShopPackageBatchPricing), AdminOrder: admin.NewOrderHandler(svc.Order), H5Order: h5.NewOrderHandler(svc.Order), - PaymentCallback: callback.NewPaymentHandler(svc.Order, deps.WechatPayment), + H5Recharge: h5.NewRechargeHandler(svc.Recharge), + PaymentCallback: callback.NewPaymentHandler(svc.Order, svc.Recharge, deps.WechatPayment), } } diff --git a/internal/bootstrap/services.go b/internal/bootstrap/services.go index 6a4e9c1..bd6ab5e 100644 --- a/internal/bootstrap/services.go +++ b/internal/bootstrap/services.go @@ -24,6 +24,7 @@ import ( permissionSvc "github.com/break/junhong_cmp_fiber/internal/service/permission" personalCustomerSvc "github.com/break/junhong_cmp_fiber/internal/service/personal_customer" purchaseValidationSvc "github.com/break/junhong_cmp_fiber/internal/service/purchase_validation" + rechargeSvc "github.com/break/junhong_cmp_fiber/internal/service/recharge" roleSvc "github.com/break/junhong_cmp_fiber/internal/service/role" shopSvc "github.com/break/junhong_cmp_fiber/internal/service/shop" shopAccountSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_account" @@ -67,6 +68,7 @@ type services struct { CommissionStats *commissionStatsSvc.Service PurchaseValidation *purchaseValidationSvc.Service Order *orderSvc.Service + Recharge *rechargeSvc.Service } func initServices(s *stores, deps *Dependencies) *services { @@ -120,5 +122,6 @@ func initServices(s *stores, deps *Dependencies) *services { CommissionStats: commissionStatsSvc.New(s.ShopSeriesCommissionStats), PurchaseValidation: purchaseValidation, Order: orderSvc.New(deps.DB, s.Order, s.OrderItem, s.Wallet, purchaseValidation, s.ShopSeriesAllocationConfig, s.ShopSeriesAllocation, s.IotCard, s.Device, deps.WechatPayment, deps.QueueClient, deps.Logger), + Recharge: rechargeSvc.New(deps.DB, s.Recharge, s.Wallet, s.WalletTransaction, s.IotCard, s.Device, s.ShopSeriesAllocation, s.CommissionRecord, deps.Logger), } } diff --git a/internal/bootstrap/stores.go b/internal/bootstrap/stores.go index db5c510..11029d2 100644 --- a/internal/bootstrap/stores.go +++ b/internal/bootstrap/stores.go @@ -38,6 +38,7 @@ type stores struct { ShopSeriesCommissionStats *postgres.ShopSeriesCommissionStatsStore Order *postgres.OrderStore OrderItem *postgres.OrderItemStore + Recharge *postgres.RechargeStore } func initStores(deps *Dependencies) *stores { @@ -75,5 +76,6 @@ func initStores(deps *Dependencies) *stores { ShopSeriesCommissionStats: postgres.NewShopSeriesCommissionStatsStore(deps.DB), Order: postgres.NewOrderStore(deps.DB, deps.Redis), OrderItem: postgres.NewOrderItemStore(deps.DB, deps.Redis), + Recharge: postgres.NewRechargeStore(deps.DB, deps.Redis), } } diff --git a/internal/bootstrap/types.go b/internal/bootstrap/types.go index e2e7228..bde2074 100644 --- a/internal/bootstrap/types.go +++ b/internal/bootstrap/types.go @@ -43,6 +43,7 @@ type Handlers struct { ShopPackageBatchPricing *admin.ShopPackageBatchPricingHandler AdminOrder *admin.OrderHandler H5Order *h5.OrderHandler + H5Recharge *h5.RechargeHandler PaymentCallback *callback.PaymentHandler } diff --git a/pkg/openapi/handlers.go b/pkg/openapi/handlers.go index 7ef1834..9a10784 100644 --- a/pkg/openapi/handlers.go +++ b/pkg/openapi/handlers.go @@ -44,6 +44,7 @@ func BuildDocHandlers() *bootstrap.Handlers { ShopPackageBatchPricing: admin.NewShopPackageBatchPricingHandler(nil), AdminOrder: admin.NewOrderHandler(nil), H5Order: h5.NewOrderHandler(nil), - PaymentCallback: callback.NewPaymentHandler(nil, nil), + H5Recharge: h5.NewRechargeHandler(nil), + PaymentCallback: callback.NewPaymentHandler(nil, nil, nil), } }