优化结构

This commit is contained in:
Yvan
2026-08-28 11:10:57 +08:00
parent 5b17f47141
commit 676fa4d952
10 changed files with 91 additions and 80 deletions
-1
View File
@@ -5,7 +5,6 @@ package config
// serializer to hand out a snapshot a caller may safely mutate. Each function
// returns nil for a nil input.
func Clone(value *Config) *Config { return cloneConfig(value) }
func CloneData(value *Data) *Data { return cloneData(value) }
func CloneAdmin(value *Admin) *Admin { return cloneAdmin(value) }
func CloneDatabase(value *Database) *Database { return clonePtr(value) }
func CloneStorage(value *Storage) *Storage { return cloneStorage(value) }
+6 -8
View File
@@ -21,8 +21,6 @@ import (
"strings"
"testing"
"kra/internal/paymentkit"
gopayAlipay "github.com/go-pay/gopay/alipay"
gopayDouyin "github.com/go-pay/gopay/douyin"
gopayWechat "github.com/go-pay/gopay/wechat"
@@ -177,7 +175,7 @@ func TestWechatV2GoPayCallbackVerificationAndSandboxAmount(t *testing.T) {
t.Errorf("read request: %v", err)
return
}
requestValues, err = paymentkit.XMLValues(body)
requestValues, err = testXMLValues(body)
if err != nil {
t.Errorf("parse request: %v", err)
return
@@ -190,7 +188,7 @@ func TestWechatV2GoPayCallbackVerificationAndSandboxAmount(t *testing.T) {
}
response := map[string]string{"return_code": "SUCCESS", "return_msg": "OK", "result_code": "SUCCESS", "prepay_id": "prepay"}
response["sign"] = wechatV2Sign(response, key, "MD5")
_, _ = w.Write(paymentkit.XMLEncode(response))
_, _ = w.Write(testXMLEncode(response))
}))
defer server.Close()
@@ -219,7 +217,7 @@ func TestWechatV2GoPayCallbackVerificationAndSandboxAmount(t *testing.T) {
if callbackValues["sign"] != originalSign {
t.Fatal("verification mutated source values")
}
callbackBody := paymentkit.XMLEncode(callbackValues)
callbackBody := testXMLEncode(callbackValues)
callbackResult, err := (&wechatV2Adapter{}).Callback(context.Background(), &bizpayment.PaymentCallback{Body: callbackBody}, map[string]any{
"app_id": "wx-test", "merchant_id": "mch-test", "mch_key": key,
})
@@ -243,7 +241,7 @@ func TestWechatV2MicropayUsesGoPaySDKAndValidatesIdentities(t *testing.T) {
t.Errorf("read request: %v", err)
return
}
requestValues, err = paymentkit.XMLValues(body)
requestValues, err = testXMLValues(body)
if err != nil {
t.Errorf("parse request: %v", err)
return
@@ -263,7 +261,7 @@ func TestWechatV2MicropayUsesGoPaySDKAndValidatesIdentities(t *testing.T) {
"transaction_id": "WX-TRANSACTION-1", "total_fee": "123", "cash_fee": "123", "fee_type": "CNY",
}
response["sign"] = wechatV2Sign(response, key, "MD5")
_, _ = w.Write(paymentkit.XMLEncode(response))
_, _ = w.Write(testXMLEncode(response))
}))
defer server.Close()
@@ -344,7 +342,7 @@ func TestWechatV2MicropayRejectsInvalidSuccessResponse(t *testing.T) {
}
tc.mutate(response)
response["sign"] = wechatV2Sign(response, key, "MD5")
_, _ = w.Write(paymentkit.XMLEncode(response))
_, _ = w.Write(testXMLEncode(response))
}))
defer server.Close()
+2 -4
View File
@@ -12,8 +12,6 @@ import (
"net/http/httptest"
"testing"
"kra/internal/paymentkit"
"github.com/go-pay/gopay"
gopayQQ "github.com/go-pay/gopay/qq"
)
@@ -55,7 +53,7 @@ func TestQQCreateKeepsClientPaymentDataOutOfDurableIdentities(t *testing.T) {
http.Error(w, "invalid XML", http.StatusBadRequest)
return
}
values, err := paymentkit.XMLValues(body)
values, err := testXMLValues(body)
if err != nil {
t.Errorf("parse request XML: %v", err)
http.Error(w, "invalid XML", http.StatusBadRequest)
@@ -81,7 +79,7 @@ func TestQQCreateKeepsClientPaymentDataOutOfDurableIdentities(t *testing.T) {
for key, value := range response {
encoded[key] = fmt.Sprint(value)
}
_, _ = w.Write(paymentkit.XMLEncode(encoded))
_, _ = w.Write(testXMLEncode(encoded))
}))
result, err := (&qqAdapter{}).Create(context.Background(), &bizpayment.PaymentRequest{
@@ -1,4 +1,4 @@
package paymentkit
package payment
import (
"bytes"
@@ -8,12 +8,12 @@ import (
"strings"
)
type xmlValue struct {
type testXMLValue struct {
XMLName xml.Name
Value string `xml:",chardata"`
}
func XMLValues(raw []byte) (map[string]string, error) {
func testXMLValues(raw []byte) (map[string]string, error) {
decoder := xml.NewDecoder(bytes.NewReader(raw))
result := map[string]string{}
for {
@@ -28,7 +28,7 @@ func XMLValues(raw []byte) (map[string]string, error) {
if !ok || start.Name.Local == "xml" {
continue
}
var value xmlValue
var value testXMLValue
if err = decoder.DecodeElement(&value, &start); err != nil {
return nil, err
}
@@ -38,7 +38,7 @@ func XMLValues(raw []byte) (map[string]string, error) {
}
}
func XMLEncode(values map[string]string) []byte {
func testXMLEncode(values map[string]string) []byte {
var b strings.Builder
b.WriteString("<xml>")
keys := make([]string, 0, len(values))
-26
View File
@@ -15,14 +15,6 @@ func JSONObject(raw []byte) map[string]any {
return object
}
func NestedString(value any, keys ...string) string {
found := nestedValue(value, keys...)
if found == nil {
return ""
}
return strings.TrimSpace(fmt.Sprint(found))
}
func StringAtPath(value any, path string) string {
found := ValueAtPath(value, path)
if found == nil {
@@ -46,21 +38,3 @@ func ValueAtPath(value any, path string) any {
}
return current
}
func nestedValue(value any, keys ...string) any {
object, ok := value.(map[string]any)
if !ok {
return nil
}
for _, key := range keys {
if found, exists := object[key]; exists && found != nil && fmt.Sprint(found) != "" {
return found
}
}
for _, nestedKey := range []string{"data", "result", "order", "transaction", "response"} {
if found := nestedValue(object[nestedKey], keys...); found != nil {
return found
}
}
return nil
}
+3 -3
View File
@@ -2,10 +2,10 @@ package paymentkit
import "testing"
func TestNestedAndPathValues(t *testing.T) {
func TestJSONObjectAndPathValues(t *testing.T) {
object := JSONObject([]byte(`{"data":{"status":"SUCCESS","amount":100}}`))
if got := NestedString(object, "status"); got != "SUCCESS" {
t.Fatalf("NestedString = %q", got)
if object == nil {
t.Fatal("JSONObject returned nil")
}
if got := StringAtPath(object, "data.amount"); got != "100" {
t.Fatalf("StringAtPath = %q", got)
+24 -9
View File
@@ -2,7 +2,6 @@ package dto
import (
"encoding/json"
integrationbiz "kra/internal/biz/integration"
)
type IntegrationConfigRequest struct {
@@ -11,12 +10,28 @@ type IntegrationConfigRequest struct {
}
type IntegrationConfigResponse struct {
Kind string `json:"kind"`
Provider string `json:"provider"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Enabled bool `json:"enabled"`
Configured bool `json:"configured"`
Config json.RawMessage `json:"config"`
Fields []integrationbiz.IntegrationConfigField `json:"fields"`
Kind string `json:"kind"`
Provider string `json:"provider"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Enabled bool `json:"enabled"`
Configured bool `json:"configured"`
Config json.RawMessage `json:"config"`
Fields []IntegrationConfigField `json:"fields"`
}
type IntegrationConfigField struct {
Key string `json:"key"`
Label string `json:"label"`
Type string `json:"type"`
Required bool `json:"required"`
Secret bool `json:"secret"`
Placeholder string `json:"placeholder,omitempty"`
Description string `json:"description,omitempty"`
Options []IntegrationConfigOption `json:"options,omitempty"`
}
type IntegrationConfigOption struct {
Label string `json:"label"`
Value any `json:"value"`
}
@@ -38,7 +38,7 @@ func (s *IntegrationConfigService) List(ctx context.Context, kind string) ([]*dt
enabled = config.Enabled
delete(byProvider, definition.Provider)
}
result = append(result, &dto.IntegrationConfigResponse{Kind: definition.Kind, Provider: definition.Provider, Name: definition.Name, Description: definition.Description, Enabled: enabled, Configured: configured, Config: values, Fields: definition.Fields})
result = append(result, &dto.IntegrationConfigResponse{Kind: definition.Kind, Provider: definition.Provider, Name: definition.Name, Description: definition.Description, Enabled: enabled, Configured: configured, Config: values, Fields: integrationFieldsDTO(definition.Fields)})
}
for _, config := range configs {
if _, exists := byProvider[config.Provider]; !exists {
@@ -59,7 +59,7 @@ func (s *IntegrationConfigService) Find(ctx context.Context, kind, provider stri
if found {
response.Name = definition.Name
response.Description = definition.Description
response.Fields = definition.Fields
response.Fields = integrationFieldsDTO(definition.Fields)
response.Config = mergeConfigJSON(definition.Defaults, config.Values)
}
return response, nil
@@ -90,3 +90,21 @@ func mergeConfigJSON(defaults map[string]any, raw json.RawMessage) json.RawMessa
encoded, _ := json.Marshal(values)
return encoded
}
func integrationFieldsDTO(fields []integrationbiz.IntegrationConfigField) []dto.IntegrationConfigField {
if fields == nil {
return nil
}
out := make([]dto.IntegrationConfigField, 0, len(fields))
for _, field := range fields {
item := dto.IntegrationConfigField{Key: field.Key, Label: field.Label, Type: field.Type, Required: field.Required, Secret: field.Secret, Placeholder: field.Placeholder, Description: field.Description}
if field.Options != nil {
item.Options = make([]dto.IntegrationConfigOption, 0, len(field.Options))
for _, option := range field.Options {
item.Options = append(item.Options, dto.IntegrationConfigOption{Label: option.Label, Value: option.Value})
}
}
out = append(out, item)
}
return out
}