优化结构
This commit is contained in:
@@ -213,6 +213,11 @@ func DefaultIntegrationConfig(kind, provider string) map[string]any {
|
||||
}
|
||||
|
||||
func mergeIntegrationDefaults(defaults, values map[string]any) map[string]any {
|
||||
return MergeIntegrationDefaults(defaults, values)
|
||||
}
|
||||
|
||||
// MergeIntegrationDefaults returns a new map with stored values overriding defaults.
|
||||
func MergeIntegrationDefaults(defaults, values map[string]any) map[string]any {
|
||||
out := make(map[string]any, len(defaults)+len(values))
|
||||
for key, value := range defaults {
|
||||
out[key] = value
|
||||
|
||||
@@ -158,51 +158,51 @@ type PaymentConfirmation struct {
|
||||
}
|
||||
|
||||
type PaymentResult struct {
|
||||
Provider string `json:"provider"`
|
||||
Status string `json:"status"`
|
||||
TradeNo string `json:"tradeNo"`
|
||||
ProviderTradeNo string `json:"providerTradeNo"`
|
||||
Amount int64 `json:"amount"`
|
||||
PayerPaidAmount int64 `json:"payerPaidAmount,omitempty"`
|
||||
CashPaidAmount int64 `json:"cashPaidAmount,omitempty"`
|
||||
PointPaidAmount int64 `json:"pointPaidAmount,omitempty"`
|
||||
DiscountAmount int64 `json:"discountAmount,omitempty"`
|
||||
ProviderDiscountAmount int64 `json:"providerDiscountAmount,omitempty"`
|
||||
MerchantDiscountAmount int64 `json:"merchantDiscountAmount,omitempty"`
|
||||
SettlementAmount int64 `json:"settlementAmount,omitempty"`
|
||||
Currency string `json:"currency"`
|
||||
PayerCurrency string `json:"payerCurrency,omitempty"`
|
||||
AmountBreakdownKnown bool `json:"amountBreakdownKnown"`
|
||||
Duplicate bool `json:"duplicate"`
|
||||
Payload json.RawMessage `json:"payload"`
|
||||
OrderStatus string `json:"orderStatus,omitempty"`
|
||||
FulfillmentStatus string `json:"fulfillmentStatus,omitempty"`
|
||||
RefundStatus string `json:"refundStatus,omitempty"`
|
||||
EventID string `json:"-"`
|
||||
QueryID string `json:"-"`
|
||||
SuccessAck PaymentCallbackAck `json:"-"`
|
||||
FailureAck PaymentCallbackAck `json:"-"`
|
||||
Provider string
|
||||
Status string
|
||||
TradeNo string
|
||||
ProviderTradeNo string
|
||||
Amount int64
|
||||
PayerPaidAmount int64
|
||||
CashPaidAmount int64
|
||||
PointPaidAmount int64
|
||||
DiscountAmount int64
|
||||
ProviderDiscountAmount int64
|
||||
MerchantDiscountAmount int64
|
||||
SettlementAmount int64
|
||||
Currency string
|
||||
PayerCurrency string
|
||||
AmountBreakdownKnown bool
|
||||
Duplicate bool
|
||||
Payload json.RawMessage
|
||||
OrderStatus string
|
||||
FulfillmentStatus string
|
||||
RefundStatus string
|
||||
EventID string
|
||||
QueryID string
|
||||
SuccessAck PaymentCallbackAck
|
||||
FailureAck PaymentCallbackAck
|
||||
}
|
||||
|
||||
// PaymentTestStage is one step of a provider connectivity test. A skipped
|
||||
// query/refund is reported explicitly because a prepay flow cannot be marked
|
||||
// paid without a sandbox payer interaction.
|
||||
type PaymentTestStage struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message,omitempty"`
|
||||
TradeNo string `json:"tradeNo,omitempty"`
|
||||
Duration int64 `json:"durationMs,omitempty"`
|
||||
Name string
|
||||
Status string
|
||||
Message string
|
||||
TradeNo string
|
||||
Duration int64
|
||||
}
|
||||
|
||||
type PaymentTestResult struct {
|
||||
Provider string `json:"provider"`
|
||||
TradeNo string `json:"tradeNo"`
|
||||
Passed bool `json:"passed"`
|
||||
FullFlow bool `json:"fullFlow"`
|
||||
Mode string `json:"mode,omitempty"`
|
||||
Stages []PaymentTestStage `json:"stages"`
|
||||
Result *PaymentResult `json:"result,omitempty"`
|
||||
Provider string
|
||||
TradeNo string
|
||||
Passed bool
|
||||
FullFlow bool
|
||||
Mode string
|
||||
Stages []PaymentTestStage
|
||||
Result *PaymentResult
|
||||
}
|
||||
|
||||
type PaymentCallbackAck struct {
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package system
|
||||
|
||||
import "context"
|
||||
|
||||
type AccessControlUsecase struct {
|
||||
authorities AuthorityAccessRepo
|
||||
apis APIRepo
|
||||
}
|
||||
|
||||
func NewAccessControlUsecase(authorities AuthorityAccessRepo, apis APIRepo) *AccessControlUsecase {
|
||||
return &AccessControlUsecase{authorities: authorities, apis: apis}
|
||||
}
|
||||
|
||||
func (uc *AccessControlUsecase) Authorize(ctx context.Context, authorityID uint, path, method string) (bool, error) {
|
||||
return uc.apis.Authorize(ctx, authorityID, path, method)
|
||||
}
|
||||
|
||||
func (uc *AccessControlUsecase) ResolveDataScope(ctx context.Context, authorityID, userID uint) (DataScope, error) {
|
||||
return uc.authorities.ResolveDataScope(ctx, authorityID, userID)
|
||||
}
|
||||
@@ -45,6 +45,23 @@ func NewAuthorityUsecase(repo AuthorityAccessRepo) *AuthorityUsecase {
|
||||
return &AuthorityUsecase{AuthorityAccessRepo: repo}
|
||||
}
|
||||
|
||||
type AccessControlUsecase struct {
|
||||
authorities AuthorityAccessRepo
|
||||
apis APIRepo
|
||||
}
|
||||
|
||||
func NewAccessControlUsecase(authorities AuthorityAccessRepo, apis APIRepo) *AccessControlUsecase {
|
||||
return &AccessControlUsecase{authorities: authorities, apis: apis}
|
||||
}
|
||||
|
||||
func (uc *AccessControlUsecase) Authorize(ctx context.Context, authorityID uint, path, method string) (bool, error) {
|
||||
return uc.apis.Authorize(ctx, authorityID, path, method)
|
||||
}
|
||||
|
||||
func (uc *AccessControlUsecase) ResolveDataScope(ctx context.Context, authorityID, userID uint) (DataScope, error) {
|
||||
return uc.authorities.ResolveDataScope(ctx, authorityID, userID)
|
||||
}
|
||||
|
||||
func (uc *AuthorityUsecase) AuthorityTree(ctx context.Context) ([]*Authority, error) {
|
||||
items, err := uc.ListAuthorities(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,6 +21,25 @@ type MediaRepo interface {
|
||||
UploadRepo
|
||||
}
|
||||
|
||||
type StoredFile struct {
|
||||
Name string
|
||||
Path string
|
||||
URL string
|
||||
Size int64
|
||||
LastModified time.Time
|
||||
ContentType string
|
||||
}
|
||||
|
||||
// FileStorage owns the persistence boundary for uploaded files.
|
||||
type FileStorage interface {
|
||||
Put(context.Context, string, io.Reader) (*StoredFile, error)
|
||||
Open(context.Context, string) (io.ReadCloser, error)
|
||||
Delete(context.Context, string) error
|
||||
Compose(context.Context, []string, string) (*StoredFile, string, error)
|
||||
DeletePrefix(context.Context, string) error
|
||||
List(context.Context, string, string, int) ([]*StoredFile, string, bool, error)
|
||||
}
|
||||
|
||||
type MediaUsecase struct {
|
||||
MediaRepo
|
||||
files FileStorage
|
||||
|
||||
@@ -6,13 +6,18 @@ import (
|
||||
)
|
||||
|
||||
type SystemParameter struct {
|
||||
ID uint
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
ID uint
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Name string
|
||||
Key string
|
||||
Value string
|
||||
Desc string
|
||||
}
|
||||
|
||||
type SystemParameterFilter struct {
|
||||
Name string
|
||||
Key string
|
||||
Value string
|
||||
Desc string
|
||||
StartCreatedAt *time.Time
|
||||
EndCreatedAt *time.Time
|
||||
}
|
||||
@@ -23,7 +28,7 @@ type ParameterRepo interface {
|
||||
DeleteParameters(context.Context, []string) error
|
||||
FindParameterByID(context.Context, string) (*SystemParameter, error)
|
||||
FindParameterByKey(context.Context, string) (*SystemParameter, error)
|
||||
ListParameters(context.Context, int, int, *SystemParameter) ([]*SystemParameter, int64, error)
|
||||
ListParameters(context.Context, int, int, *SystemParameterFilter) ([]*SystemParameter, int64, error)
|
||||
}
|
||||
|
||||
type ParameterUsecase struct{ ParameterRepo }
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StoredFile struct {
|
||||
Name string
|
||||
Path string
|
||||
URL string
|
||||
Size int64
|
||||
LastModified time.Time
|
||||
ContentType string
|
||||
}
|
||||
|
||||
// FileStorage owns the persistence boundary for uploaded files.
|
||||
type FileStorage interface {
|
||||
Put(context.Context, string, io.Reader) (*StoredFile, error)
|
||||
Open(context.Context, string) (io.ReadCloser, error)
|
||||
Delete(context.Context, string) error
|
||||
Compose(context.Context, []string, string) (*StoredFile, string, error)
|
||||
DeletePrefix(context.Context, string) error
|
||||
List(context.Context, string, string, int) ([]*StoredFile, string, bool, error)
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package integration
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
|
||||
integrationbiz "kra/internal/biz/integration"
|
||||
"kra/pkg/database/migration"
|
||||
@@ -66,13 +67,9 @@ func ensurePaymentIntegrationConfigs(db *gorm.DB) error {
|
||||
return err
|
||||
}
|
||||
values := integrationObject(json.RawMessage(row.Config))
|
||||
changed := false
|
||||
for key, value := range defaults {
|
||||
if _, exists := values[key]; !exists {
|
||||
values[key] = value
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
merged := integrationbiz.MergeIntegrationDefaults(defaults, values)
|
||||
changed := !reflect.DeepEqual(values, merged)
|
||||
values = merged
|
||||
if changed {
|
||||
encoded, marshalErr := json.Marshal(values)
|
||||
if marshalErr != nil {
|
||||
|
||||
@@ -57,7 +57,7 @@ func (r *parameterRepo) FindParameterByKey(ctx context.Context, key string) (*sy
|
||||
}
|
||||
return parameterFromPO(po), nil
|
||||
}
|
||||
func (r *parameterRepo) ListParameters(ctx context.Context, page, size int, q *system.SystemParameter) ([]*system.SystemParameter, int64, error) {
|
||||
func (r *parameterRepo) ListParameters(ctx context.Context, page, size int, q *system.SystemParameterFilter) ([]*system.SystemParameter, int64, error) {
|
||||
db := r.data.DB().WithContext(ctx).Model(¶meterPO{})
|
||||
if q != nil {
|
||||
if q.StartCreatedAt != nil && q.EndCreatedAt != nil {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"kra/internal/paymentkit"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -435,7 +436,7 @@ func alipayCreateMethod(extra, config map[string]any) (string, error) {
|
||||
if value == "" {
|
||||
value = firstAny(config, "method", "pay_method", "trade_type", "channel")
|
||||
}
|
||||
normalized := strings.NewReplacer(".", "_", "-", "_", " ", "_").Replace(strings.ToLower(strings.TrimSpace(value)))
|
||||
normalized := paymentkit.NormalizePaymentMethod(value)
|
||||
switch normalized {
|
||||
case "", "create", "trade_create", "alipay_trade_create", "jsapi", "miniapp", "mini_program":
|
||||
return "alipay.trade.create", nil
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"kra/internal/paymentkit"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -207,7 +208,7 @@ func allinpayCreateMethod(extra, config map[string]any) (string, error) {
|
||||
if value == "" {
|
||||
value = firstAny(config, "method", "pay_method", "trade_type")
|
||||
}
|
||||
normalized := strings.NewReplacer(".", "_", "-", "_", " ", "_").Replace(strings.ToLower(strings.TrimSpace(value)))
|
||||
normalized := paymentkit.NormalizePaymentMethod(value)
|
||||
switch normalized {
|
||||
case "", "pay", "unified", "unified_pay":
|
||||
return "pay", nil
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"kra/internal/paymentkit"
|
||||
"strings"
|
||||
|
||||
"github.com/go-pay/gopay"
|
||||
@@ -110,7 +111,7 @@ func douyinCreateMethod(extra, config map[string]any) (string, error) {
|
||||
if value == "" {
|
||||
value = firstAny(config, "method", "pay_method", "trade_type", "pay_type", "channel")
|
||||
}
|
||||
normalized := strings.NewReplacer(".", "_", "-", "_", " ", "_").Replace(strings.ToLower(strings.TrimSpace(value)))
|
||||
normalized := paymentkit.NormalizePaymentMethod(value)
|
||||
switch normalized {
|
||||
case "", "jsapi", "js_api", "mini", "mini_program", "miniprogram", "applet":
|
||||
return "jsapi", nil
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"kra/internal/paymentkit"
|
||||
"strings"
|
||||
|
||||
"github.com/go-pay/gopay"
|
||||
@@ -71,7 +72,7 @@ func lakalaCreateMethod(extra, config map[string]any) string {
|
||||
if method == "" {
|
||||
method = firstAny(config, "method", "pay_method", "trade_type")
|
||||
}
|
||||
return strings.NewReplacer(".", "_", "-", "_", " ", "_").Replace(strings.ToLower(strings.TrimSpace(method)))
|
||||
return paymentkit.NormalizePaymentMethod(method)
|
||||
}
|
||||
|
||||
func lakalaCreateResult(tradeNo string, rsp *lakala.PaymentRsp) (*bizpayment.PaymentResult, error) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"kra/internal/paymentkit"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -89,7 +90,7 @@ func saobeiCreateMethod(extra, config map[string]any) (string, error) {
|
||||
if value == "" {
|
||||
value = firstAny(config, "method", "pay_method", "trade_type")
|
||||
}
|
||||
normalized := strings.NewReplacer(".", "_", "-", "_", " ", "_").Replace(strings.ToLower(strings.TrimSpace(value)))
|
||||
normalized := paymentkit.NormalizePaymentMethod(value)
|
||||
switch normalized {
|
||||
case "", "mini", "mini_pay", "miniapp", "mini_app", "mini_program", "miniprogram", "jsapi", "js_api":
|
||||
return "mini", nil
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
bizpayment "kra/internal/biz/payment"
|
||||
"kra/internal/paymentkit"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -180,7 +181,7 @@ func wechatV2CreateMethod(extra, config map[string]any) (string, error) {
|
||||
if value == "" {
|
||||
value = firstAny(config, "trade_type", "pay_type", "method", "pay_method", "channel")
|
||||
}
|
||||
normalized := strings.NewReplacer(".", "_", "-", "_", " ", "_").Replace(strings.ToLower(strings.TrimSpace(value)))
|
||||
normalized := paymentkit.NormalizePaymentMethod(value)
|
||||
switch normalized {
|
||||
case "", "jsapi", "js_api", "mini", "miniapp", "mini_program", "miniprogram", "applet":
|
||||
return gopayWechat.TradeType_JsApi, nil
|
||||
|
||||
@@ -33,6 +33,12 @@ func NormalizeRefundStatus(value, fallback string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// NormalizePaymentMethod canonicalizes provider method identifiers while
|
||||
// leaving provider-specific classification to the integration adapter.
|
||||
func NormalizePaymentMethod(value string) string {
|
||||
return strings.NewReplacer(".", "_", "-", "_", " ", "_").Replace(strings.ToLower(strings.TrimSpace(value)))
|
||||
}
|
||||
|
||||
func ConfiguredInt64(values map[string]any, key string, fallback int64) int64 {
|
||||
value, ok := values[key]
|
||||
if !ok {
|
||||
|
||||
@@ -84,15 +84,9 @@ func (s *IntegrationConfigService) Delete(ctx context.Context, kind, provider st
|
||||
}
|
||||
|
||||
func mergeConfigJSON(defaults map[string]any, raw json.RawMessage) json.RawMessage {
|
||||
values := make(map[string]any, len(defaults))
|
||||
for key, value := range defaults {
|
||||
values[key] = value
|
||||
}
|
||||
stored := map[string]any{}
|
||||
_ = json.Unmarshal(raw, &stored)
|
||||
for key, value := range stored {
|
||||
values[key] = value
|
||||
}
|
||||
values := integrationbiz.MergeIntegrationDefaults(defaults, stored)
|
||||
encoded, _ := json.Marshal(values)
|
||||
return encoded
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ func (s *ParameterService) UpdateParameterRequest(ctx context.Context, req *dto.
|
||||
return s.UpdateParameter(ctx, parameterDomain(req))
|
||||
}
|
||||
func (s *ParameterService) ParametersFilter(ctx context.Context, page, size int, name, key string, start, end *time.Time) ([]*dto.SystemParameterResponse, int64, error) {
|
||||
return s.Parameters(ctx, page, size, &system.SystemParameter{Name: name, Key: key, StartCreatedAt: start, EndCreatedAt: end})
|
||||
return s.Parameters(ctx, page, size, &system.SystemParameterFilter{Name: name, Key: key, StartCreatedAt: start, EndCreatedAt: end})
|
||||
}
|
||||
func parameterDTO(v *system.SystemParameter) *dto.SystemParameterResponse {
|
||||
return &dto.SystemParameterResponse{ID: v.ID, CreatedAt: v.CreatedAt, UpdatedAt: v.UpdatedAt, DeletedAt: nil, Name: v.Name, Key: v.Key, Value: v.Value, Desc: v.Desc}
|
||||
}
|
||||
func (s *ParameterService) Parameters(ctx context.Context, page, size int, q *system.SystemParameter) ([]*dto.SystemParameterResponse, int64, error) {
|
||||
func (s *ParameterService) Parameters(ctx context.Context, page, size int, q *system.SystemParameterFilter) ([]*dto.SystemParameterResponse, int64, error) {
|
||||
items, total, err := s.uc.ListParameters(ctx, page, size, q)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
|
||||
Reference in New Issue
Block a user