优化结构

This commit is contained in:
Yvan
2026-08-29 02:58:00 +08:00
parent 3d108ebdfe
commit b6d25c1a0f
24 changed files with 1657 additions and 224 deletions
+39 -3
View File
@@ -72,6 +72,8 @@ type PaymentRequest struct {
BusinessID string `json:"businessId"`
PaymentMode string `json:"paymentMode"`
OriginalAmount int64 `json:"originalAmount"`
UserAgent string `json:"-"`
DeviceID string `json:"-"`
}
// PaymentRefundRequest carries the durable provider identities needed to
@@ -415,6 +417,23 @@ func (uc *PaymentUsecase) Orders(ctx context.Context, page, pageSize int, filter
return uc.orders.ListPaymentOrders(ctx, page, pageSize, filter)
}
func (uc *PaymentUsecase) OrderSummary(ctx context.Context, filter PaymentOrderFilter) (*PaymentOrderSummary, error) {
if uc.orders == nil {
return nil, errors.New("支付订单仓储未接入")
}
return uc.orders.SummarizePaymentOrders(ctx, filter)
}
func (uc *PaymentUsecase) OrderEvents(ctx context.Context, provider, tradeNo string, limit int) ([]*PaymentEvent, error) {
if uc.orders == nil {
return nil, errors.New("支付订单仓储未接入")
}
if !validPaymentText(provider, 64) || !validPaymentText(tradeNo, 128) {
return nil, errors.New("支付订单事件查询参数不完整")
}
return uc.orders.ListPaymentEvents(ctx, provider, tradeNo, limit)
}
func (uc *PaymentUsecase) Create(ctx context.Context, req *PaymentRequest) (*PaymentResult, error) {
if req == nil || !validPaymentText(req.Provider, 64) || !validPaymentText(req.TradeNo, 128) || !validPaymentText(req.BusinessType, 64) || !validPaymentText(req.BusinessID, 128) {
return nil, errors.New("支付参数不完整")
@@ -644,6 +663,9 @@ func (uc *PaymentUsecase) createWithOrder(ctx context.Context, req *PaymentReque
ConfirmationID: paymentConfirmationID(req.Provider, req.TradeNo),
RequestFingerprint: paymentOrderFingerprint(req, extra),
Extra: extra,
ClientIP: req.ClientIP,
UserAgent: req.UserAgent,
DeviceID: req.DeviceID,
}
order, created, err := uc.orders.CreatePaymentOrder(ctx, order)
if err != nil {
@@ -691,7 +713,9 @@ func (uc *PaymentUsecase) createWithOrder(ctx context.Context, req *PaymentReque
if err = validatePaymentBreakdown(result); err != nil {
return nil, fmt.Errorf("内部支付金额拆分无效: %w", err)
}
if _, err = uc.orders.RecordPaymentCreate(ctx, req.Provider, req.TradeNo, paymentProviderUpdate(result)); err != nil {
update := paymentProviderUpdate(result)
update.EventSource = PaymentInternal
if _, err = uc.orders.RecordPaymentCreate(ctx, req.Provider, req.TradeNo, update); err != nil {
return nil, err
}
return uc.reconcilePaymentResult(ctx, result, nil)
@@ -707,7 +731,9 @@ func (uc *PaymentUsecase) createWithOrder(ctx context.Context, req *PaymentReque
uc.logger.Error(ctx, "payment.order.provider_create_invalid", "provider", req.Provider, "trade_no", req.TradeNo, "error", err)
return nil, err
}
order, err = uc.orders.RecordPaymentCreate(ctx, req.Provider, req.TradeNo, paymentProviderUpdate(result))
update := paymentProviderUpdate(result)
update.EventSource = req.Provider
order, err = uc.orders.RecordPaymentCreate(ctx, req.Provider, req.TradeNo, update)
if err != nil {
uc.logger.Error(ctx, "payment.order.provider_create_record_failed", "provider", req.Provider, "trade_no", req.TradeNo, "error", err)
return nil, err
@@ -773,7 +799,17 @@ func (uc *PaymentUsecase) reconcilePaymentResult(ctx context.Context, result, ca
return fail(err)
}
}
order, err = uc.orders.ApplyPaymentResult(ctx, result.Provider, result.TradeNo, paymentProviderUpdate(result))
update := paymentProviderUpdate(result)
operation := PaymentOperationFromContext(ctx)
update.EventSource = operation.Source
update.EventType = PaymentEventPaymentSynchronized
if callbackSource != nil {
update.EventType = PaymentEventPaymentCallback
if update.EventSource == "" {
update.EventSource = result.Provider
}
}
order, err = uc.orders.ApplyPaymentResult(ctx, result.Provider, result.TradeNo, update)
if err != nil {
uc.logger.Error(ctx, "payment.order.result_record_failed", "provider", result.Provider, "trade_no", result.TradeNo, "error", err)
return fail(err)
+94
View File
@@ -0,0 +1,94 @@
package payment
import (
"context"
"strings"
"time"
)
const (
PaymentEventOrderCreated = "order_created"
PaymentEventProviderCreated = "provider_created"
PaymentEventPaymentSynchronized = "payment_synchronized"
PaymentEventPaymentCallback = "payment_callback"
PaymentEventFulfillmentStarted = "fulfillment_started"
PaymentEventFulfillmentFinished = "fulfillment_finished"
PaymentEventRefundStarted = "refund_started"
PaymentEventRefundSubmitted = "refund_submitted"
PaymentEventRefundConfirmed = "refund_confirmed"
)
// PaymentOperation describes who or what initiated a payment state change.
// It is carried in context so repo method signatures remain focused on domain
// state while event persistence can still retain transport-level attribution.
type PaymentOperation struct {
Source string
Reason string
OperatorID uint
OperatorName string
ClientIP string
UserAgent string
DeviceID string
}
type paymentOperationContextKey struct{}
func WithPaymentOperation(ctx context.Context, operation PaymentOperation) context.Context {
if ctx == nil {
ctx = context.Background()
}
return context.WithValue(ctx, paymentOperationContextKey{}, operation)
}
func PaymentOperationFromContext(ctx context.Context) PaymentOperation {
if ctx == nil {
return PaymentOperation{}
}
operation, _ := ctx.Value(paymentOperationContextKey{}).(PaymentOperation)
operation.Source = strings.TrimSpace(operation.Source)
operation.Reason = strings.TrimSpace(operation.Reason)
operation.OperatorName = strings.TrimSpace(operation.OperatorName)
operation.ClientIP = strings.TrimSpace(operation.ClientIP)
operation.UserAgent = strings.TrimSpace(operation.UserAgent)
operation.DeviceID = strings.TrimSpace(operation.DeviceID)
return operation
}
type PaymentEvent struct {
ID uint64
Provider string
TradeNo string
Type string
Source string
Status string
ProviderStatus string
Message string
EventID string
PayloadHash string
Amount int64
Currency string
OperatorID uint
OperatorName string
ClientIP string
UserAgent string
DeviceID string
CreatedAt time.Time
}
type PaymentCurrencySummary struct {
Currency string
OrderAmount int64
PaidAmount int64
RefundedAmount int64
SettlementAmount int64
NetAmount int64
}
type PaymentOrderSummary struct {
OrderCount int64
PendingCount int64
PaidCount int64
RefundedCount int64
IssueCount int64
Currencies []PaymentCurrencySummary
}
+21 -6
View File
@@ -88,6 +88,9 @@ type PaymentOrder struct {
RefundedAt *time.Time
FulfillmentLeaseUntil *time.Time
RefundLeaseUntil *time.Time
ClientIP string
UserAgent string
DeviceID string
}
type PaymentProviderUpdate struct {
@@ -109,21 +112,33 @@ type PaymentProviderUpdate struct {
EventID string
PayloadHash string
CreatePayload json.RawMessage
EventType string
EventSource string
EventMessage string
}
type PaymentOrderFilter struct {
Provider string
TradeNo string
BusinessType string
BusinessID string
PaymentStatus string
RefundStatus string
Provider string
TradeNo string
ProviderTradeNo string
Keyword string
BusinessType string
BusinessID string
PaymentStatus string
RefundStatus string
CreatedFrom *time.Time
CreatedTo *time.Time
PaidFrom *time.Time
PaidTo *time.Time
IssueOnly bool
}
type PaymentOrderRepo interface {
CreatePaymentOrder(context.Context, *PaymentOrder) (order *PaymentOrder, created bool, err error)
FindPaymentOrder(context.Context, string, string) (*PaymentOrder, error)
ListPaymentOrders(context.Context, int, int, PaymentOrderFilter) ([]*PaymentOrder, int64, error)
SummarizePaymentOrders(context.Context, PaymentOrderFilter) (*PaymentOrderSummary, error)
ListPaymentEvents(context.Context, string, string, int) ([]*PaymentEvent, error)
RecordPaymentCreate(context.Context, string, string, *PaymentProviderUpdate) (*PaymentOrder, error)
ApplyPaymentResult(context.Context, string, string, *PaymentProviderUpdate) (*PaymentOrder, error)
BeginPaymentFulfillment(context.Context, string, string, time.Duration) (order *PaymentOrder, token string, duplicate bool, err error)
+10
View File
@@ -52,6 +52,16 @@ func (r *paymentOrderRepoStub) ListPaymentOrders(context.Context, int, int, Paym
}
return []*PaymentOrder{r.order}, 1, nil
}
func (r *paymentOrderRepoStub) SummarizePaymentOrders(context.Context, PaymentOrderFilter) (*PaymentOrderSummary, error) {
count := int64(0)
if r.order != nil {
count = 1
}
return &PaymentOrderSummary{OrderCount: count}, nil
}
func (r *paymentOrderRepoStub) ListPaymentEvents(context.Context, string, string, int) ([]*PaymentEvent, error) {
return []*PaymentEvent{}, nil
}
func (r *paymentOrderRepoStub) RecordPaymentCreate(_ context.Context, _, _ string, update *PaymentProviderUpdate) (*PaymentOrder, error) {
r.order.PaymentStatus = PaymentStatusPending
r.order.CreatePayload = append(r.order.CreatePayload[:0], update.CreatePayload...)