优化结构
This commit is contained in:
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user