Files
junhong_cmp_fiber/internal/routes/payment_merchant.go
break bb06cc89c5
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
修复
2026-09-14 09:45:47 +08:00

54 lines
6.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package routes
import (
"github.com/gofiber/fiber/v2"
"github.com/break/junhong_cmp_fiber/internal/handler/admin"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/openapi"
)
// requirePaymentMerchantAccess 校验当前用户是否有权访问支付商户配置,
// 仅允许超级管理员和平台用户,其他角色直接返回无权限错误。
func requirePaymentMerchantAccess(handler fiber.Handler) fiber.Handler {
return func(c *fiber.Ctx) error {
kind := middleware.GetUserTypeFromContext(c.UserContext())
if kind != constants.UserTypeSuperAdmin && kind != constants.UserTypePlatform {
return errors.New(errors.CodeForbidden, "无权限访问支付商户配置")
}
return handler(c)
}
}
// paymentMerchantCredentialDoc 说明商户 credentials 允许的键,与 validateMerchantConfiguration 的校验口径一致。
// credentials 是 JSONB生成的 OpenAPI 只能给它一个通用 object 模式,因此键枚举写进操作说明供前端枚举。
const paymentMerchantCredentialDoc = `商户凭证 credentials 为扁平 JSON 对象,键名与渠道配置字段一致;必填键由 payment_method 与 provider_type 组合决定:
- payment_method=wechat、provider_type=wechatwx_mch_id、wx_api_v3_key、wx_cert_content、wx_key_content、wx_serial_no、wx_notify_url
- payment_method=wechat、provider_type=wechat_v2wx_mch_id、wx_api_v2_key、wx_notify_url
- payment_method=wechat、provider_type=fuioufy_mchnt_cd、fy_ins_cd、fy_term_id、fy_private_key、fy_public_key、fy_api_url、fy_notify_url
- payment_method=alipay、provider_type=alipayali_app_id、ali_private_key、ali_public_key、ali_notify_url、ali_return_url
可选键:微信商户可附 wx_api_v2_key支付宝商户可附 ali_production布尔是否生产环境与 ali_pay_expire_minutes整数支付过期分钟数
除 ali_production 与 ali_pay_expire_minutes 外凭证值必须为字符串merchant_identity 必须分别等于 wx_mch_id、fy_mchnt_cd 或 ali_app_id。
商户凭证为敏感信息,仅超级管理员与平台用户可读可写,日志、审计与支付快照不保存凭证内容。`
func registerPaymentMerchantRoutes(router fiber.Router, handler *admin.PaymentMerchantHandler, doc *openapi.Generator, basePath string) {
group := router
wrap := requirePaymentMerchantAccess
Register(group, doc, basePath, "GET", "/payment-merchants", wrap(handler.ListMerchants), RouteSpec{Summary: "查询支付商户", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"支付商户管理"}, Input: new(dto.PaymentMerchantListRequest), Output: new(dto.PaymentMerchantResponse), Auth: true})
Register(group, doc, basePath, "POST", "/payment-merchants", wrap(handler.CreateMerchant), RouteSpec{Summary: "创建支付商户", Description: "仅超级管理员和平台用户可访问。\n\n" + paymentMerchantCredentialDoc, Tags: []string{"支付商户管理"}, Input: new(dto.PaymentMerchantRequest), Output: new(dto.PaymentMerchantResponse), Auth: true})
Register(group, doc, basePath, "GET", "/payment-merchants/:id", wrap(handler.GetMerchant), RouteSpec{Summary: "查询支付商户详情", Description: "仅超级管理员和平台用户可访问。\n\n" + paymentMerchantCredentialDoc, Tags: []string{"支付商户管理"}, Input: new(dto.IDReq), Output: new(dto.PaymentMerchantResponse), Auth: true})
Register(group, doc, basePath, "PUT", "/payment-merchants/:id", wrap(handler.UpdateMerchant), RouteSpec{Summary: "更新支付商户", Description: "仅超级管理员和平台用户可访问。\n\n" + paymentMerchantCredentialDoc, Tags: []string{"支付商户管理"}, Input: new(dto.IDReq), Body: new(dto.PaymentMerchantUpdateRequest), Output: new(dto.PaymentMerchantResponse), Auth: true})
Register(group, doc, basePath, "DELETE", "/payment-merchants/:id", wrap(handler.DeleteMerchant), RouteSpec{Summary: "删除支付商户", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"支付商户管理"}, Input: new(dto.IDReq), Body: new(dto.PaymentMerchantDeleteRequest), Output: nil, Auth: true})
Register(group, doc, basePath, "GET", "/payment-merchant-pools", wrap(handler.ListPools), RouteSpec{Summary: "查询商户池", Description: "仅超级管理员和平台用户可访问。支持分页,返回当前页商户池及其有序成员。", Tags: []string{"商户池管理"}, Input: new(dto.PaymentMerchantPoolListRequest), Output: new(dto.PaymentMerchantPoolResponse), Auth: true})
Register(group, doc, basePath, "GET", "/payment-merchant-pools/:id", wrap(handler.GetPool), RouteSpec{Summary: "查询商户池详情", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"商户池管理"}, Input: new(dto.IDReq), Output: new(dto.PaymentMerchantPoolResponse), Auth: true})
Register(group, doc, basePath, "POST", "/payment-merchant-pools", wrap(handler.CreatePool), RouteSpec{Summary: "创建商户池", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"商户池管理"}, Input: new(dto.PaymentMerchantPoolRequest), Output: new(dto.PaymentMerchantPoolResponse), Auth: true})
Register(group, doc, basePath, "PUT", "/payment-merchant-pools/:id", wrap(handler.UpdatePool), RouteSpec{Summary: "更新商户池", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"商户池管理"}, Input: new(dto.IDReq), Body: new(dto.PaymentMerchantPoolRequest), Output: new(dto.PaymentMerchantPoolResponse), Auth: true})
Register(group, doc, basePath, "POST", "/payment-merchant-pools/:id/enable", wrap(handler.EnablePool), RouteSpec{Summary: "启用商户池", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"商户池管理"}, Input: new(dto.IDReq), Output: new(dto.PaymentMerchantPoolResponse), Auth: true})
Register(group, doc, basePath, "POST", "/payment-merchant-pools/:id/disable", wrap(handler.DisablePool), RouteSpec{Summary: "停用商户池", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"商户池管理"}, Input: new(dto.IDReq), Output: new(dto.PaymentMerchantPoolResponse), Auth: true})
Register(group, doc, basePath, "GET", "/wechat-authorizations", wrap(handler.GetAuthorization), RouteSpec{Summary: "获取微信授权配置", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"微信授权配置"}, Output: new(dto.WechatAuthorizationResponse), Auth: true})
Register(group, doc, basePath, "PUT", "/wechat-authorizations/current", wrap(handler.SaveAuthorization), RouteSpec{Summary: "保存微信授权配置", Description: "仅超级管理员和平台用户可访问。", Tags: []string{"微信授权配置"}, Input: new(dto.WechatAuthorizationRequest), Output: new(dto.WechatAuthorizationResponse), Auth: true})
}