优化支付配置启用规则

This commit is contained in:
yml
2026-06-06 23:43:57 +08:00
parent bb624acae7
commit 8ae76036a8
5 changed files with 85 additions and 27 deletions
@@ -96,7 +96,7 @@ func (h *Handler) Create(c *gin.Context) {
if err == ErrNameRequired || err == ErrMerchantIDRequired || err == ErrGatewayURLRequired ||
err == ErrSignKeyRequired || err == ErrNotifyKeyRequired || err == ErrInvalidProvider ||
err == ErrNotifyURLRequired || err == ErrInvalidSignType || err == ErrAppIDRequired ||
err == ErrSerialNoRequired || err == ErrTermNoRequired {
err == ErrInvalidStatus || err == ErrSerialNoRequired || err == ErrTermNoRequired {
response.BadRequest(c, err.Error())
return
}
@@ -139,7 +139,7 @@ func (h *Handler) Update(c *gin.Context) {
response.NotFound(c, "配置不存在")
return
}
if err == ErrInvalidSignType || err == ErrNotifyURLRequired {
if err == ErrInvalidSignType || err == ErrInvalidStatus || err == ErrNotifyURLRequired {
response.BadRequest(c, err.Error())
return
}
@@ -171,15 +171,6 @@ func (r *Repository) Create(req CreateRequest, actorID uint64, meta AuditMeta) (
var dto ConfigDTO
err := r.db.Transaction(func(tx *gorm.DB) error {
// 如果设置为默认,先取消同 provider 的其他默认配置
if req.IsDefault {
if err := tx.Model(&model.PaymentMerchantConfig{}).
Where("provider = ? AND is_default = ?", req.Provider, true).
Update("is_default", false).Error; err != nil {
return err
}
}
// 加密密钥
encryptedSignKey, err := r.encryptor.Encrypt(req.SignKey)
if err != nil {
@@ -198,6 +189,15 @@ func (r *Repository) Create(req CreateRequest, actorID uint64, meta AuditMeta) (
if environment == "" {
environment = "production"
}
isDefault := req.IsDefault
if status == "active" {
if err := deactivateOtherConfigs(tx, 0, actorID); err != nil {
return err
}
isDefault = true
} else {
isDefault = false
}
item := model.PaymentMerchantConfig{
Name: req.Name,
@@ -212,7 +212,7 @@ func (r *Repository) Create(req CreateRequest, actorID uint64, meta AuditMeta) (
JSPayFlag: firstNonEmpty(req.JSPayFlag, "2"),
SignType: firstNonEmpty(req.SignType, defaultSignType(req.Provider)),
ExtraConfig: req.ExtraConfig,
IsDefault: req.IsDefault,
IsDefault: isDefault,
Status: status,
Environment: environment,
BusinessTags: req.BusinessTags,
@@ -247,6 +247,9 @@ func (r *Repository) Update(id uint64, req UpdateRequest, actorID uint64, meta A
if req.SignType != nil && *req.SignType != "" && !isValidSignType(*req.SignType) {
return nil, ErrInvalidSignType
}
if req.Status != nil && !isValidStatus(*req.Status) {
return nil, ErrInvalidStatus
}
if req.NotifyURL != nil && *req.NotifyURL == "" {
return nil, ErrNotifyURLRequired
}
@@ -261,15 +264,6 @@ func (r *Repository) Update(id uint64, req UpdateRequest, actorID uint64, meta A
return err
}
// 如果设置为默认,先取消同 provider 的其他默认配置
if req.IsDefault != nil && *req.IsDefault && !item.IsDefault {
if err := tx.Model(&model.PaymentMerchantConfig{}).
Where("provider = ? AND is_default = ? AND id != ?", item.Provider, true, id).
Update("is_default", false).Error; err != nil {
return err
}
}
updates := make(map[string]any)
if req.Name != nil {
updates["name"] = *req.Name
@@ -326,6 +320,20 @@ func (r *Repository) Update(id uint64, req UpdateRequest, actorID uint64, meta A
}
updates["updated_by"] = actorID
finalStatus := item.Status
if req.Status != nil {
finalStatus = *req.Status
}
if finalStatus == "active" {
if err := deactivateOtherConfigs(tx, id, actorID); err != nil {
return err
}
updates["status"] = "active"
updates["is_default"] = true
} else {
updates["is_default"] = false
}
if err := tx.Model(&item).Updates(updates).Error; err != nil {
return err
}
@@ -430,6 +438,20 @@ func (r *Repository) RecordUsage(configID uint64, paymentOrderID uint64, provide
})
}
// deactivateOtherConfigs 保证全局同一时间只有一个启用配置。
func deactivateOtherConfigs(tx *gorm.DB, activeID uint64, actorID uint64) error {
db := tx.Model(&model.PaymentMerchantConfig{}).
Where("status = ? OR is_default = ?", "active", true)
if activeID > 0 {
db = db.Where("id != ?", activeID)
}
return db.Updates(map[string]any{
"status": "disabled",
"is_default": false,
"updated_by": actorID,
}).Error
}
// toDTO 转换为 DTO
func (r *Repository) toDTO(item model.PaymentMerchantConfig, includeSecret bool) (ConfigDTO, error) {
dto := ConfigDTO{
@@ -492,6 +514,9 @@ func (r *Repository) validateCreateRequest(req CreateRequest) error {
if req.SignType != "" && !isValidSignType(req.SignType) {
return ErrInvalidSignType
}
if req.Status != "" && !isValidStatus(req.Status) {
return ErrInvalidStatus
}
// leshua 特定验证
if req.Provider == "leshua" {
@@ -555,6 +580,10 @@ func isValidSignType(value string) bool {
return value == "MD5" || value == "SHA256withRSA"
}
func isValidStatus(value string) bool {
return value == "active" || value == "disabled" || value == "testing"
}
func extraString(config map[string]any, key string) string {
if config == nil {
return ""