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