收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
@@ -5,6 +5,7 @@ package wechat_config
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
@@ -12,10 +13,12 @@ import (
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
systemconfigapp "github.com/break/junhong_cmp_fiber/internal/application/systemconfig"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditfailure"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
@@ -24,11 +27,6 @@ import (
|
||||
// Redis 缓存键
|
||||
const redisActiveConfigKey = "wechat:config:active"
|
||||
|
||||
// AuditServiceInterface 审计日志服务接口
|
||||
type AuditServiceInterface interface {
|
||||
LogOperation(ctx context.Context, log *model.AccountOperationLog)
|
||||
}
|
||||
|
||||
// Service 微信参数配置业务服务
|
||||
type Service struct {
|
||||
store *postgres.WechatConfigStore
|
||||
@@ -36,7 +34,7 @@ type Service struct {
|
||||
rechargeOrderStore *postgres.RechargeOrderStore
|
||||
agentRechargeStore *postgres.AgentRechargeStore
|
||||
paymentStore *postgres.PaymentStore
|
||||
auditService AuditServiceInterface
|
||||
audit systemconfigapp.AuditWriter
|
||||
redis *redis.Client
|
||||
logger *zap.Logger
|
||||
}
|
||||
@@ -48,7 +46,7 @@ func New(
|
||||
rechargeOrderStore *postgres.RechargeOrderStore,
|
||||
agentRechargeStore *postgres.AgentRechargeStore,
|
||||
paymentStore *postgres.PaymentStore,
|
||||
auditService AuditServiceInterface,
|
||||
audit systemconfigapp.AuditWriter,
|
||||
rdb *redis.Client,
|
||||
logger *zap.Logger,
|
||||
) *Service {
|
||||
@@ -58,7 +56,7 @@ func New(
|
||||
rechargeOrderStore: rechargeOrderStore,
|
||||
agentRechargeStore: agentRechargeStore,
|
||||
paymentStore: paymentStore,
|
||||
auditService: auditService,
|
||||
audit: audit,
|
||||
redis: rdb,
|
||||
logger: logger,
|
||||
}
|
||||
@@ -69,8 +67,17 @@ func New(
|
||||
func (s *Service) Create(ctx context.Context, req *dto.CreateWechatConfigRequest) (*dto.WechatConfigResponse, error) {
|
||||
// 根据 provider_type 校验必填字段
|
||||
if err := s.validateProviderFields(req); err != nil {
|
||||
s.recordAuditFailure(ctx, systemconfigapp.ChangeAudit{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx), OperationType: constants.AuditOperationPaymentConfigCreate,
|
||||
Description: "拒绝创建非法支付连接配置", ConfigKey: "payment_config.new:" + req.Name,
|
||||
DisplayName: req.Name, Identity: map[string]any{"name": req.Name, "provider_type": req.ProviderType, "credentials_configured": paymentRequestCredentialsConfigured(req)},
|
||||
Result: constants.AuditResultDenied, ErrorCode: strconv.Itoa(errors.CodeInvalidParam), ErrorSummary: "支付连接配置字段校验失败",
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
if s.audit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "支付配置审计接缝未配置")
|
||||
}
|
||||
|
||||
var desc *string
|
||||
if req.Description != "" {
|
||||
@@ -118,28 +125,17 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateWechatConfigRequest
|
||||
}
|
||||
config.Creator = middleware.GetUserIDFromContext(ctx)
|
||||
|
||||
if err := s.store.Create(ctx, config); err != nil {
|
||||
err := s.store.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.store.WithTx(tx).Create(ctx, config); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.writeAudit(ctx, tx, constants.AuditOperationPaymentConfigCreate, "创建支付连接配置", nil, config)
|
||||
})
|
||||
if err != nil {
|
||||
s.recordPaymentFailure(ctx, constants.AuditOperationPaymentConfigCreate, "创建支付连接配置失败", config, err)
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "创建微信支付配置失败")
|
||||
}
|
||||
|
||||
// 审计日志
|
||||
afterData := model.JSONB{
|
||||
"id": config.ID,
|
||||
"name": config.Name,
|
||||
"provider_type": config.ProviderType,
|
||||
}
|
||||
go s.auditService.LogOperation(ctx, &model.AccountOperationLog{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx),
|
||||
OperatorType: middleware.GetUserTypeFromContext(ctx),
|
||||
OperatorName: "",
|
||||
OperationType: "create",
|
||||
OperationDesc: fmt.Sprintf("创建微信支付配置:%s", config.Name),
|
||||
AfterData: afterData,
|
||||
RequestID: middleware.GetRequestIDFromContext(ctx),
|
||||
IPAddress: middleware.GetIPFromContext(ctx),
|
||||
UserAgent: middleware.GetUserAgentFromContext(ctx),
|
||||
})
|
||||
|
||||
return dto.FromWechatConfigModel(config), nil
|
||||
}
|
||||
|
||||
@@ -200,6 +196,10 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateWechatConf
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "获取微信支付配置失败")
|
||||
}
|
||||
if s.audit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "支付配置审计接缝未配置")
|
||||
}
|
||||
before := *config
|
||||
|
||||
// 合并字段:指针非 nil 时更新,敏感字段空字符串表示保持原值
|
||||
if req.Name != nil {
|
||||
@@ -256,7 +256,14 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateWechatConf
|
||||
|
||||
config.Updater = middleware.GetUserIDFromContext(ctx)
|
||||
|
||||
if err := s.store.Update(ctx, config); err != nil {
|
||||
err = s.store.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.store.WithTx(tx).Update(ctx, config); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.writeAudit(ctx, tx, constants.AuditOperationPaymentConfigUpdate, "更新支付连接配置", &before, config)
|
||||
})
|
||||
if err != nil {
|
||||
s.recordPaymentFailure(ctx, constants.AuditOperationPaymentConfigUpdate, "更新支付连接配置失败", config, err)
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "更新微信支付配置失败")
|
||||
}
|
||||
|
||||
@@ -265,24 +272,6 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateWechatConf
|
||||
s.clearActiveConfigCache(ctx)
|
||||
}
|
||||
|
||||
afterData := model.JSONB{
|
||||
"id": config.ID,
|
||||
"name": config.Name,
|
||||
"provider_type": config.ProviderType,
|
||||
"is_active": config.IsActive,
|
||||
}
|
||||
go s.auditService.LogOperation(ctx, &model.AccountOperationLog{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx),
|
||||
OperatorType: middleware.GetUserTypeFromContext(ctx),
|
||||
OperatorName: "",
|
||||
OperationType: "update",
|
||||
OperationDesc: fmt.Sprintf("更新微信支付配置:%s", config.Name),
|
||||
AfterData: afterData,
|
||||
RequestID: middleware.GetRequestIDFromContext(ctx),
|
||||
IPAddress: middleware.GetIPFromContext(ctx),
|
||||
UserAgent: middleware.GetUserAgentFromContext(ctx),
|
||||
})
|
||||
|
||||
return dto.FromWechatConfigModel(config), nil
|
||||
}
|
||||
|
||||
@@ -296,9 +285,13 @@ func (s *Service) Delete(ctx context.Context, id uint) error {
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "获取微信支付配置失败")
|
||||
}
|
||||
if s.audit == nil {
|
||||
return errors.New(errors.CodeInvalidStatus, "支付配置审计接缝未配置")
|
||||
}
|
||||
|
||||
// 不允许删除正在激活的配置
|
||||
if config.IsActive {
|
||||
s.recordPaymentDenied(ctx, constants.AuditOperationPaymentConfigDelete, "拒绝删除生效中的支付连接配置", config, errors.CodeWechatConfigActive)
|
||||
return errors.New(errors.CodeWechatConfigActive)
|
||||
}
|
||||
|
||||
@@ -314,32 +307,23 @@ func (s *Service) Delete(ctx context.Context, id uint) error {
|
||||
}
|
||||
|
||||
if pendingOrders > 0 || pendingRecharges > 0 {
|
||||
s.recordPaymentDenied(ctx, constants.AuditOperationPaymentConfigDelete, "拒绝删除存在在途业务的支付连接配置", config, errors.CodeWechatConfigHasPendingOrders)
|
||||
return errors.New(errors.CodeWechatConfigHasPendingOrders)
|
||||
}
|
||||
|
||||
if err := s.store.SoftDelete(ctx, id); err != nil {
|
||||
err = s.store.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.store.WithTx(tx).SoftDelete(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.writeAudit(ctx, tx, constants.AuditOperationPaymentConfigDelete, "删除支付连接配置", config, nil)
|
||||
})
|
||||
if err != nil {
|
||||
s.recordPaymentFailure(ctx, constants.AuditOperationPaymentConfigDelete, "删除支付连接配置失败", config, err)
|
||||
return errors.Wrap(errors.CodeInternalError, err, "删除微信支付配置失败")
|
||||
}
|
||||
|
||||
s.clearActiveConfigCache(ctx)
|
||||
|
||||
beforeData := model.JSONB{
|
||||
"id": config.ID,
|
||||
"name": config.Name,
|
||||
"provider_type": config.ProviderType,
|
||||
}
|
||||
go s.auditService.LogOperation(ctx, &model.AccountOperationLog{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx),
|
||||
OperatorType: middleware.GetUserTypeFromContext(ctx),
|
||||
OperatorName: "",
|
||||
OperationType: "delete",
|
||||
OperationDesc: fmt.Sprintf("删除微信支付配置:%s", config.Name),
|
||||
BeforeData: beforeData,
|
||||
RequestID: middleware.GetRequestIDFromContext(ctx),
|
||||
IPAddress: middleware.GetIPFromContext(ctx),
|
||||
UserAgent: middleware.GetUserAgentFromContext(ctx),
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -353,19 +337,32 @@ func (s *Service) Activate(ctx context.Context, id uint) (*dto.WechatConfigRespo
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "获取微信支付配置失败")
|
||||
}
|
||||
|
||||
// 记录旧的激活配置名称
|
||||
oldActiveName := ""
|
||||
oldActive, oldErr := s.store.GetActive(ctx)
|
||||
if oldErr == nil && oldActive != nil {
|
||||
oldActiveName = oldActive.Name
|
||||
if s.audit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "支付配置审计接缝未配置")
|
||||
}
|
||||
before := *config
|
||||
|
||||
// 保留原激活配置快照,确保自动停用也进入该配置自身时间线。
|
||||
oldActive, oldErr := s.store.GetActive(ctx)
|
||||
|
||||
// 事务内激活
|
||||
db := s.store.DB()
|
||||
if err := db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
return s.store.ActivateInTx(ctx, tx, id)
|
||||
if err := s.store.ActivateInTx(ctx, tx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
after := before
|
||||
after.IsActive = true
|
||||
if oldErr == nil && oldActive != nil && oldActive.ID != id {
|
||||
oldAfter := *oldActive
|
||||
oldAfter.IsActive = false
|
||||
if err := s.writeAudit(ctx, tx, constants.AuditOperationPaymentConfigDeactivate, "激活其他配置时停用原支付连接配置", oldActive, &oldAfter); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return s.writeAudit(ctx, tx, constants.AuditOperationPaymentConfigActivate, "激活支付连接配置", &before, &after)
|
||||
}); err != nil {
|
||||
s.recordPaymentFailure(ctx, constants.AuditOperationPaymentConfigActivate, "激活支付连接配置失败", config, err)
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "激活微信支付配置失败")
|
||||
}
|
||||
|
||||
@@ -374,22 +371,6 @@ func (s *Service) Activate(ctx context.Context, id uint) (*dto.WechatConfigRespo
|
||||
// 重新查询最新状态
|
||||
config, _ = s.store.GetByID(ctx, id)
|
||||
|
||||
desc := fmt.Sprintf("激活微信支付配置:%s", config.Name)
|
||||
if oldActiveName != "" && oldActiveName != config.Name {
|
||||
desc = fmt.Sprintf("激活微信支付配置:%s(原激活配置:%s)", config.Name, oldActiveName)
|
||||
}
|
||||
go s.auditService.LogOperation(ctx, &model.AccountOperationLog{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx),
|
||||
OperatorType: middleware.GetUserTypeFromContext(ctx),
|
||||
OperatorName: "",
|
||||
OperationType: "activate",
|
||||
OperationDesc: desc,
|
||||
AfterData: model.JSONB{"id": config.ID, "name": config.Name, "is_active": true},
|
||||
RequestID: middleware.GetRequestIDFromContext(ctx),
|
||||
IPAddress: middleware.GetIPFromContext(ctx),
|
||||
UserAgent: middleware.GetUserAgentFromContext(ctx),
|
||||
})
|
||||
|
||||
return dto.FromWechatConfigModel(config), nil
|
||||
}
|
||||
|
||||
@@ -403,8 +384,21 @@ func (s *Service) Deactivate(ctx context.Context, id uint) (*dto.WechatConfigRes
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "获取微信支付配置失败")
|
||||
}
|
||||
if s.audit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "支付配置审计接缝未配置")
|
||||
}
|
||||
before := *config
|
||||
after := before
|
||||
after.IsActive = false
|
||||
|
||||
if err := s.store.Deactivate(ctx, id); err != nil {
|
||||
err = s.store.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.store.WithTx(tx).Deactivate(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.writeAudit(ctx, tx, constants.AuditOperationPaymentConfigDeactivate, "停用支付连接配置", &before, &after)
|
||||
})
|
||||
if err != nil {
|
||||
s.recordPaymentFailure(ctx, constants.AuditOperationPaymentConfigDeactivate, "停用支付连接配置失败", config, err)
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "停用微信支付配置失败")
|
||||
}
|
||||
|
||||
@@ -413,21 +407,109 @@ func (s *Service) Deactivate(ctx context.Context, id uint) (*dto.WechatConfigRes
|
||||
// 重新查询最新状态
|
||||
config, _ = s.store.GetByID(ctx, id)
|
||||
|
||||
go s.auditService.LogOperation(ctx, &model.AccountOperationLog{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx),
|
||||
OperatorType: middleware.GetUserTypeFromContext(ctx),
|
||||
OperatorName: "",
|
||||
OperationType: "deactivate",
|
||||
OperationDesc: fmt.Sprintf("停用微信支付配置:%s", config.Name),
|
||||
AfterData: model.JSONB{"id": config.ID, "name": config.Name, "is_active": false},
|
||||
RequestID: middleware.GetRequestIDFromContext(ctx),
|
||||
IPAddress: middleware.GetIPFromContext(ctx),
|
||||
UserAgent: middleware.GetUserAgentFromContext(ctx),
|
||||
})
|
||||
|
||||
return dto.FromWechatConfigModel(config), nil
|
||||
}
|
||||
|
||||
func (s *Service) writeAudit(ctx context.Context, tx *gorm.DB, operation, description string, before, after *model.WechatConfig) error {
|
||||
config := after
|
||||
if config == nil {
|
||||
config = before
|
||||
}
|
||||
resourceID := strconv.FormatUint(uint64(config.ID), 10)
|
||||
requestID := ""
|
||||
if value := middleware.GetRequestIDFromContext(ctx); value != nil {
|
||||
requestID = *value
|
||||
}
|
||||
return s.audit.WriteConfigChange(ctx, tx, systemconfigapp.ChangeAudit{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx), OperationType: operation, Description: description,
|
||||
ConfigKey: "payment_config." + resourceID, Module: "payment", ResourceID: &resourceID,
|
||||
DisplayName: config.Name, Identity: paymentConfigIdentity(config),
|
||||
BeforeData: paymentConfigAuditSnapshot(before), AfterData: paymentConfigAuditSnapshot(after),
|
||||
RequestID: requestID, CorrelationID: requestID,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) recordPaymentDenied(ctx context.Context, operation, description string, config *model.WechatConfig, code int) {
|
||||
s.recordAuditFailure(ctx, paymentFailureAudit(ctx, operation, description, config, constants.AuditResultDenied, code))
|
||||
}
|
||||
|
||||
func (s *Service) recordPaymentFailure(ctx context.Context, operation, description string, config *model.WechatConfig, _ error) {
|
||||
s.recordAuditFailure(ctx, paymentFailureAudit(ctx, operation, description, config, constants.AuditResultFailed, errors.CodeDatabaseError))
|
||||
}
|
||||
|
||||
func (s *Service) recordAuditFailure(ctx context.Context, audit systemconfigapp.ChangeAudit) {
|
||||
if s.audit == nil || s.store == nil || s.store.DB() == nil || audit.OperatorID == 0 || audit.ConfigKey == "" {
|
||||
return
|
||||
}
|
||||
if value := middleware.GetRequestIDFromContext(ctx); value != nil {
|
||||
audit.RequestID = *value
|
||||
audit.CorrelationID = *value
|
||||
}
|
||||
if err := s.store.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
return s.audit.WriteConfigChange(ctx, tx, audit)
|
||||
}); err != nil {
|
||||
auditfailure.RecordSecondaryWriteFailure(audit.OperationType, audit.ConfigKey, audit.RequestID, audit.CorrelationID, audit.ErrorCode, err)
|
||||
}
|
||||
}
|
||||
|
||||
func paymentFailureAudit(ctx context.Context, operation, description string, config *model.WechatConfig, result string, code int) systemconfigapp.ChangeAudit {
|
||||
resourceID := strconv.FormatUint(uint64(config.ID), 10)
|
||||
return systemconfigapp.ChangeAudit{
|
||||
OperatorID: middleware.GetUserIDFromContext(ctx), OperationType: operation, Description: description,
|
||||
ConfigKey: "payment_config." + resourceID, Module: "payment", ResourceID: &resourceID,
|
||||
DisplayName: config.Name, Identity: paymentConfigIdentity(config), BeforeData: paymentConfigAuditSnapshot(config),
|
||||
Result: result, ErrorCode: strconv.Itoa(code), ErrorSummary: description,
|
||||
}
|
||||
}
|
||||
|
||||
func paymentConfigIdentity(config *model.WechatConfig) map[string]any {
|
||||
if config == nil {
|
||||
return nil
|
||||
}
|
||||
return map[string]any{
|
||||
"id": config.ID, "name": config.Name, "provider_type": config.ProviderType,
|
||||
"is_active": config.IsActive, "credentials_configured": paymentConfigCredentialsConfigured(config),
|
||||
}
|
||||
}
|
||||
|
||||
func paymentConfigAuditSnapshot(config *model.WechatConfig) map[string]any {
|
||||
if config == nil {
|
||||
return nil
|
||||
}
|
||||
return map[string]any{
|
||||
"id": config.ID, "name": config.Name, "description": config.Description,
|
||||
"provider_type": config.ProviderType, "is_active": config.IsActive,
|
||||
"oa_app_id": config.OaAppID, "oa_oauth_redirect_url": config.OaOAuthRedirectURL,
|
||||
"miniapp_app_id": config.MiniappAppID, "wx_mch_id": config.WxMchID,
|
||||
"wx_serial_no": config.WxSerialNo, "wx_notify_url": config.WxNotifyURL,
|
||||
"fy_ins_cd": config.FyInsCd, "fy_mchnt_cd": config.FyMchntCd, "fy_term_id": config.FyTermID,
|
||||
"fy_api_url": config.FyAPIURL, "fy_notify_url": config.FyNotifyURL,
|
||||
"ali_app_id": config.AliAppID, "ali_notify_url": config.AliNotifyURL,
|
||||
"ali_return_url": config.AliReturnURL, "ali_production": config.AliProduction,
|
||||
"ali_pay_expire_minutes": config.AliPayExpireMinutes,
|
||||
"credentials_configured": paymentConfigCredentialsConfigured(config),
|
||||
"oauth_configured": config.OaAppSecret != "" || config.OaToken != "" || config.OaAesKey != "" || config.MiniappAppSecret != "",
|
||||
"wechat_payment_configured": config.WxAPIV3Key != "" || config.WxAPIV2Key != "" || config.WxCertContent != "" || config.WxKeyContent != "",
|
||||
"fuiou_configured": config.FyPrivateKey != "" || config.FyPublicKey != "",
|
||||
"alipay_configured": config.AliPrivateKey != "" || config.AliPublicKey != "",
|
||||
}
|
||||
}
|
||||
|
||||
func paymentConfigCredentialsConfigured(config *model.WechatConfig) bool {
|
||||
if config == nil {
|
||||
return false
|
||||
}
|
||||
return config.OaAppSecret != "" || config.OaToken != "" || config.OaAesKey != "" || config.MiniappAppSecret != "" ||
|
||||
config.WxAPIV3Key != "" || config.WxAPIV2Key != "" || config.WxCertContent != "" || config.WxKeyContent != "" ||
|
||||
config.FyPrivateKey != "" || config.FyPublicKey != "" || config.AliPrivateKey != "" || config.AliPublicKey != ""
|
||||
}
|
||||
|
||||
func paymentRequestCredentialsConfigured(request *dto.CreateWechatConfigRequest) bool {
|
||||
return request != nil && (request.OaAppSecret != "" || request.OaToken != "" || request.OaAesKey != "" || request.MiniappAppSecret != "" ||
|
||||
request.WxAPIV3Key != "" || request.WxAPIV2Key != "" || request.WxCertContent != "" || request.WxKeyContent != "" ||
|
||||
request.FyPrivateKey != "" || request.FyPublicKey != "" || request.AliPrivateKey != "" || request.AliPublicKey != "")
|
||||
}
|
||||
|
||||
// GetActiveConfig 获取当前生效的支付配置(带 Redis 缓存)
|
||||
// 缓存策略:命中直接返回,未命中查 DB 后缓存 5 分钟,无记录缓存 "none" 1 分钟
|
||||
func (s *Service) GetActiveConfig(ctx context.Context) (*model.WechatConfig, error) {
|
||||
|
||||
Reference in New Issue
Block a user