优化结构

This commit is contained in:
Yvan
2026-08-22 23:02:44 +08:00
parent b18baf1547
commit 64459574b2
16 changed files with 158 additions and 73 deletions
+31 -6
View File
@@ -57,6 +57,23 @@ type IntegrationConfigRepo interface {
DeleteIntegrationConfig(context.Context, string, string) error
}
// ErrPaymentConfigNotFound marks an absent payment integration row without
// exposing the storage driver's not-found error to the payment data module.
var ErrPaymentConfigNotFound = errors.New("支付渠道配置不存在")
// PaymentConfig is the storage-neutral, unmasked snapshot used by payment
// persistence. It deliberately contains no ORM or table metadata.
type PaymentConfig struct {
Enabled bool
Values json.RawMessage
}
// PaymentConfigReader is the narrow inversion seam between the payment and
// integration data modules. The integration module owns its ConfigPO.
type PaymentConfigReader interface {
ReadPaymentConfig(context.Context, string) (*PaymentConfig, error)
}
type IntegrationConnectionTester interface {
TestIntegration(context.Context, *IntegrationConfig) error
}
@@ -98,9 +115,9 @@ func (uc *IntegrationConfigUsecase) Save(ctx context.Context, config *Integratio
if !json.Valid(config.Values) {
return errors.New("集成配置必须是合法 JSON")
}
values := map[string]any{}
if err := json.Unmarshal(config.Values, &values); err != nil {
return errors.New("集成配置必须是 JSON 对象")
values, err := decodeIntegrationObject(config.Values)
if err != nil {
return err
}
if definition, ok := IntegrationDefinition(config.Kind, config.Provider); ok {
values = mergeIntegrationDefaults(definition.Defaults, values)
@@ -131,9 +148,9 @@ func (uc *IntegrationConfigUsecase) Test(ctx context.Context, config *Integratio
if !json.Valid(config.Values) {
return errors.New("集成配置必须是合法 JSON")
}
values := map[string]any{}
if err := json.Unmarshal(config.Values, &values); err != nil {
return errors.New("集成配置必须是 JSON 对象")
values, err := decodeIntegrationObject(config.Values)
if err != nil {
return err
}
if definition, ok := IntegrationDefinition(config.Kind, config.Provider); ok {
values = mergeIntegrationDefaults(definition.Defaults, values)
@@ -162,6 +179,14 @@ func normalizeIntegrationPart(value string) string {
return strings.ToLower(strings.TrimSpace(value))
}
func decodeIntegrationObject(raw json.RawMessage) (map[string]any, error) {
values := map[string]any{}
if err := json.Unmarshal(raw, &values); err != nil || values == nil {
return nil, errors.New("集成配置必须是 JSON 对象")
}
return values, nil
}
func IntegrationDefinitions(kind string) []IntegrationConfigDefinition {
kind = normalizeIntegrationPart(kind)
definitions := integrationDefinitions[kind]
@@ -96,3 +96,14 @@ func TestIntegrationConfigTestDoesNotPersistCandidate(t *testing.T) {
t.Fatalf("tested values = %#v", values)
}
}
func TestIntegrationConfigRejectsJSONNull(t *testing.T) {
repo := &integrationConfigRepoTestDouble{}
usecase := NewIntegrationConfigUsecase(repo, &integrationConnectionTesterDouble{})
if err := usecase.Save(context.Background(), &IntegrationConfig{Kind: IntegrationKindMQ, Provider: "emqx", Values: json.RawMessage("null")}); err == nil {
t.Fatal("Save() accepted JSON null as an object")
}
if err := usecase.Test(context.Background(), &IntegrationConfig{Kind: IntegrationKindMQ, Provider: "emqx", Values: json.RawMessage("null")}); err == nil {
t.Fatal("Test() accepted JSON null as an object")
}
}