Files
hfb_sys/backend/internal/modules/payment/query.go
T

127 lines
4.0 KiB
Go

package payment
import (
"context"
"gorm.io/gorm"
"hfb_sys/backend/internal/model"
)
func (r *Repository) Query(ctx context.Context, userID uint64, orderID uint64) (*PaymentDTO, error) {
var payment model.PaymentOrder
if err := r.db.WithContext(ctx).Where("order_id = ? AND user_id = ? AND biz_type = ?", orderID, userID, "order_pay").Order("id DESC").First(&payment).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPaymentNotFound
}
return nil, err
}
runtimeConfig, err := r.runtimeConfigForPayment(ctx, &payment)
if err != nil {
return nil, ErrPaymentUnavailable
}
if payment.Status == "paid" || runtimeConfig.isMockMode() {
dto := toDTO(payment)
return &dto, nil
}
if runtimeConfig.Channel == nil {
return nil, ErrPaymentUnavailable
}
resp, err := runtimeConfig.Channel.QueryPayment(ctx, payment.ThirdOrderID, payment.ProviderOrderID)
if err != nil {
return nil, err
}
if err := r.applyChannelStatus(ctx, &payment, resp.Status, resp.PayTime, resp.Raw, channelSourceQuery); err != nil {
return nil, err
}
latest, err := r.findPaymentByID(ctx, payment.ID)
if err != nil {
return nil, err
}
dto := toDTO(*latest)
return &dto, nil
}
func (r *Repository) AdminList(ctx context.Context, query AdminPaymentQuery) (*PaginatedResult, error) {
db := r.db.WithContext(ctx).Table("payment_orders AS p").
Select("p.*, COALESCE(u.phone, '') AS user_phone").
Joins("LEFT JOIN users AS u ON u.id = p.user_id")
countDB := r.db.WithContext(ctx).Model(&model.PaymentOrder{})
if query.UserID > 0 {
db = db.Where("p.user_id = ?", query.UserID)
countDB = countDB.Where("user_id = ?", query.UserID)
}
if query.OrderID > 0 {
db = db.Where("p.order_id = ?", query.OrderID)
countDB = countDB.Where("order_id = ?", query.OrderID)
}
if query.OrderNo != "" {
db = db.Where("p.order_no = ?", query.OrderNo)
countDB = countDB.Where("order_no = ?", query.OrderNo)
}
if query.BizType != "" {
db = db.Where("p.biz_type = ?", query.BizType)
countDB = countDB.Where("biz_type = ?", query.BizType)
}
if query.Status != "" {
db = db.Where("p.status = ?", query.Status)
countDB = countDB.Where("status = ?", query.Status)
}
if query.Provider != "" {
db = db.Where("p.provider = ?", query.Provider)
countDB = countDB.Where("provider = ?", query.Provider)
}
var total int64
if err := countDB.Count(&total).Error; err != nil {
return nil, err
}
offset := (query.Page - 1) * query.PageSize
var rows []adminPaymentRow
if err := db.Order("p.id DESC").Offset(offset).Limit(query.PageSize).Scan(&rows).Error; err != nil {
return nil, err
}
items := make([]AdminPaymentDTO, 0, len(rows))
for _, row := range rows {
items = append(items, row.toDTO())
}
return &PaginatedResult{Items: items, Total: total, Page: query.Page, PageSize: query.PageSize}, nil
}
func (r *Repository) findPaymentByID(ctx context.Context, paymentID uint64) (*model.PaymentOrder, error) {
var payment model.PaymentOrder
if err := r.db.WithContext(ctx).First(&payment, paymentID).Error; err != nil {
return nil, err
}
return &payment, nil
}
type adminPaymentRow struct {
model.PaymentOrder
UserPhone string
}
func (row adminPaymentRow) toDTO() AdminPaymentDTO {
errorCode, errorMessage := paymentErrorSummary(row.Status, row.RawResponse)
return AdminPaymentDTO{
ID: row.ID,
PaymentNo: row.PaymentNo,
OrderID: row.OrderID,
OrderNo: row.OrderNo,
UserID: row.UserID,
PaymentConfigID: row.PaymentConfigID,
UserPhone: row.UserPhone,
Provider: row.Provider,
MerchantID: row.MerchantID,
ThirdOrderID: row.ThirdOrderID,
ProviderOrderID: row.ProviderOrderID,
PayWay: row.PayWay,
AmountCent: row.AmountCent,
BizType: row.BizType,
Status: row.Status,
ErrorCode: errorCode,
ErrorMessage: errorMessage,
RawRequest: row.RawRequest,
RawResponse: row.RawResponse,
PaidAt: row.PaidAt,
NotifiedAt: row.NotifiedAt,
CreatedAt: row.CreatedAt,
UpdatedAt: row.UpdatedAt,
}
}