Files
pay-bridge/backend/internal/repository/payment_match.go
2026-03-13 15:51:59 +08:00

96 lines
3.5 KiB
Go

package repository
import (
"context"
"errors"
"time"
"gorm.io/gorm"
"pay-bridge/internal/model"
)
// PaymentMatchRepository 收款匹配数据访问
type PaymentMatchRepository struct {
db *gorm.DB
}
func NewPaymentMatchRepository(db *gorm.DB) *PaymentMatchRepository {
return &PaymentMatchRepository{db: db}
}
// GetAccountByNo 按账号查询子商户收款账户
func (r *PaymentMatchRepository) GetAccountByNo(ctx context.Context, accountNo string) (*model.SubMerchantAccount, error) {
var acc model.SubMerchantAccount
err := r.db.WithContext(ctx).Where("account_no = ? AND status = 1", accountNo).First(&acc).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return &acc, err
}
// GetAccountByID 按 id 查询
func (r *PaymentMatchRepository) GetAccountByID(ctx context.Context, id uint64) (*model.SubMerchantAccount, error) {
var acc model.SubMerchantAccount
err := r.db.WithContext(ctx).Where("id = ?", id).First(&acc).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return &acc, err
}
// ListAccountsByApp 查询应用下所有收款账户
func (r *PaymentMatchRepository) ListAccountsByApp(ctx context.Context, appID string) ([]*model.SubMerchantAccount, error) {
var accs []*model.SubMerchantAccount
err := r.db.WithContext(ctx).Where("app_id = ? AND status = 1", appID).Find(&accs).Error
return accs, err
}
// CreateAccount 创建收款账户
func (r *PaymentMatchRepository) CreateAccount(ctx context.Context, acc *model.SubMerchantAccount) error {
return r.db.WithContext(ctx).Create(acc).Error
}
// CreateMatchLog 创建匹配记录
func (r *PaymentMatchRepository) CreateMatchLog(ctx context.Context, log *model.PaymentMatchLog) error {
return r.db.WithContext(ctx).Create(log).Error
}
// GetMatchLogByBillNo 按渠道流水号查询(幂等检查)
func (r *PaymentMatchRepository) GetMatchLogByBillNo(ctx context.Context, channelBillNo string) (*model.PaymentMatchLog, error) {
var log model.PaymentMatchLog
err := r.db.WithContext(ctx).Where("channel_bill_no = ?", channelBillNo).First(&log).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return &log, err
}
// UpdateMatchLog 更新匹配记录
func (r *PaymentMatchRepository) UpdateMatchLog(ctx context.Context, id uint64, updates map[string]any) error {
return r.db.WithContext(ctx).Model(&model.PaymentMatchLog{}).Where("id = ?", id).Updates(updates).Error
}
// ListPendingManual 查询待人工确认的记录
func (r *PaymentMatchRepository) ListPendingManual(ctx context.Context, appID string, limit, offset int) ([]*model.PaymentMatchLog, error) {
var logs []*model.PaymentMatchLog
err := r.db.WithContext(ctx).
Joins("JOIN sub_merchant_account ON sub_merchant_account.id = payment_match_log.account_id").
Where("sub_merchant_account.app_id = ? AND payment_match_log.match_status = ?",
appID, model.MatchStatusPendingManual).
Order("payment_match_log.created_at DESC").
Limit(limit).Offset(offset).
Find(&logs).Error
return logs, err
}
// ListPayingByAmount 按金额查询指定时间窗口内的待支付订单(用于收款匹配降级)
func (r *PaymentMatchRepository) ListPayingByAmount(ctx context.Context, appID string, amount int64, window time.Duration) ([]*model.TradeOrder, error) {
var orders []*model.TradeOrder
since := time.Now().Add(-window)
err := r.db.WithContext(ctx).
Where("app_id = ? AND amount = ? AND status = ? AND created_at >= ?",
appID, amount, model.TradeStatusPaying, since).
Find(&orders).Error
return orders, err
}