package payment import ( "context" "errors" bizpayment "kra/internal/biz/payment" "time" "gorm.io/gorm" ) type paymentEventPO struct { ID uint64 `gorm:"primaryKey"` Provider string `gorm:"size:64;not null;index:idx_pay_events_order,priority:1"` TradeNo string `gorm:"size:128;not null;index:idx_pay_events_order,priority:2"` Type string `gorm:"size:64;not null;index"` Source string `gorm:"size:64;not null;index"` Status string `gorm:"size:64"` ProviderStatus string `gorm:"size:64"` Message string `gorm:"size:512"` EventID string `gorm:"size:128;index"` PayloadHash string `gorm:"size:64"` Amount int64 `gorm:"not null;default:0"` Currency string `gorm:"size:16"` OperatorID uint `gorm:"index"` OperatorName string `gorm:"size:128"` ClientIP string `gorm:"size:64"` UserAgent string `gorm:"size:512"` DeviceID string `gorm:"size:128"` CreatedAt time.Time `gorm:"index"` } func (paymentEventPO) TableName() string { return "pay_events" } func toBizPaymentEvent(po *paymentEventPO) *bizpayment.PaymentEvent { if po == nil { return nil } return &bizpayment.PaymentEvent{ ID: po.ID, Provider: po.Provider, TradeNo: po.TradeNo, Type: po.Type, Source: po.Source, Status: po.Status, ProviderStatus: po.ProviderStatus, Message: po.Message, EventID: po.EventID, PayloadHash: po.PayloadHash, Amount: po.Amount, Currency: po.Currency, OperatorID: po.OperatorID, OperatorName: po.OperatorName, ClientIP: po.ClientIP, UserAgent: po.UserAgent, DeviceID: po.DeviceID, CreatedAt: po.CreatedAt, } } func appendPaymentEvent(ctx context.Context, tx *gorm.DB, order *paymentOrderPO, event *bizpayment.PaymentEvent) error { if tx == nil || order == nil || event == nil { return nil } eventType := trimTo(event.Type, 64) if eventType == "" { return errors.New("支付事件类型为空") } operation := bizpayment.PaymentOperationFromContext(ctx) source := trimTo(event.Source, 64) if source == "" { source = trimTo(operation.Source, 64) } if source == "" { source = "system" } message := trimTo(event.Message, 512) if message == "" { message = trimTo(operation.Reason, 512) } operatorID := event.OperatorID if operatorID == 0 { operatorID = operation.OperatorID } operatorName := trimTo(event.OperatorName, 128) if operatorName == "" { operatorName = trimTo(operation.OperatorName, 128) } clientIP := trimTo(event.ClientIP, 64) if clientIP == "" { clientIP = trimTo(operation.ClientIP, 64) } userAgent := trimTo(event.UserAgent, 512) if userAgent == "" { userAgent = trimTo(operation.UserAgent, 512) } deviceID := trimTo(event.DeviceID, 128) if deviceID == "" { deviceID = trimTo(operation.DeviceID, 128) } return tx.Create(&paymentEventPO{ Provider: order.Provider, TradeNo: order.TradeNo, Type: eventType, Source: source, Status: trimTo(event.Status, 64), ProviderStatus: trimTo(event.ProviderStatus, 64), Message: message, EventID: trimTo(event.EventID, 128), PayloadHash: trimTo(event.PayloadHash, 64), Amount: event.Amount, Currency: trimTo(event.Currency, 16), OperatorID: operatorID, OperatorName: operatorName, ClientIP: clientIP, UserAgent: userAgent, DeviceID: deviceID, }).Error } func savePaymentOrderWithEvent(ctx context.Context, tx *gorm.DB, order *paymentOrderPO, event *bizpayment.PaymentEvent) error { if err := tx.Save(order).Error; err != nil { return err } return appendPaymentEvent(ctx, tx, order, event) } func (r *paymentOrderRepo) ListPaymentEvents(ctx context.Context, provider, tradeNo string, limit int) ([]*bizpayment.PaymentEvent, error) { if limit <= 0 { limit = 100 } if limit > 500 { limit = 500 } var rows []paymentEventPO if err := r.data.DB().WithContext(ctx). Where("provider = ? AND trade_no = ?", provider, tradeNo). Order("id DESC").Limit(limit).Find(&rows).Error; err != nil { return nil, err } items := make([]*bizpayment.PaymentEvent, 0, len(rows)) for i := range rows { items = append(items, toBizPaymentEvent(&rows[i])) } return items, nil }