feat: 代理充值支持线下支付凭证上传与存储
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -79,6 +79,7 @@ type AgentRechargeRecord struct {
|
||||
PaymentTransactionID *string `gorm:"column:payment_transaction_id;type:varchar(100);comment:第三方支付交易号" json:"payment_transaction_id,omitempty"`
|
||||
PaymentConfigID *uint `gorm:"column:payment_config_id;index;comment:支付配置ID(关联tb_wechat_config.id)" json:"payment_config_id,omitempty"`
|
||||
Status int `gorm:"column:status;type:int;not null;default:1;comment:充值状态(1-待支付 2-已支付 3-已完成 4-已关闭 5-已退款)" json:"status"`
|
||||
PaymentVoucherKey string `gorm:"column:payment_voucher_key;type:varchar(500);comment:支付凭证对象存储Key(线下支付时必填,微信支付时为空)" json:"payment_voucher_key,omitempty"`
|
||||
PaidAt *time.Time `gorm:"column:paid_at;comment:支付时间" json:"paid_at,omitempty"`
|
||||
CompletedAt *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at,omitempty"`
|
||||
ShopIDTag uint `gorm:"column:shop_id_tag;not null;index;comment:店铺ID标签(多租户过滤)" json:"shop_id_tag"`
|
||||
|
||||
@@ -2,9 +2,10 @@ package dto
|
||||
|
||||
// CreateAgentRechargeRequest 创建代理充值请求
|
||||
type CreateAgentRechargeRequest struct {
|
||||
ShopID uint `json:"shop_id" validate:"required" required:"true" description:"目标店铺ID,代理只能填自己店铺"`
|
||||
Amount int64 `json:"amount" validate:"required,min=10000,max=100000000" required:"true" minimum:"10000" maximum:"100000000" description:"充值金额(分),范围100元~100万元"`
|
||||
PaymentMethod string `json:"payment_method" validate:"required,oneof=wechat offline" required:"true" description:"支付方式 (wechat:微信在线支付, offline:线下转账仅平台可用)"`
|
||||
ShopID uint `json:"shop_id" validate:"required" required:"true" description:"目标店铺ID,代理只能填自己店铺"`
|
||||
Amount int64 `json:"amount" validate:"required,min=10000,max=100000000" required:"true" minimum:"10000" maximum:"100000000" description:"充值金额(分),范围100元~100万元"`
|
||||
PaymentMethod string `json:"payment_method" validate:"required,oneof=wechat offline" required:"true" description:"支付方式 (wechat:微信在线支付, offline:线下转账仅平台可用)"`
|
||||
PaymentVoucherKey string `json:"payment_voucher_key" validate:"omitempty,max=500" description:"支付凭证对象存储Key(payment_method=offline 时必填,微信支付时忽略)"`
|
||||
}
|
||||
|
||||
// AgentOfflinePayRequest 代理线下充值确认请求
|
||||
@@ -30,6 +31,7 @@ type AgentRechargeResponse struct {
|
||||
PaymentChannel string `json:"payment_channel" description:"实际支付通道 (wechat_direct:微信直连, fuyou:富友, offline:线下转账)"`
|
||||
PaymentConfigID *uint `json:"payment_config_id" description:"关联支付配置ID,线下充值为null"`
|
||||
PaymentTransactionID string `json:"payment_transaction_id" description:"第三方支付流水号"`
|
||||
PaymentVoucherKey string `json:"payment_voucher_key,omitempty" description:"支付凭证对象存储Key(线下支付时存在)"`
|
||||
Status int `json:"status" description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款)"`
|
||||
StatusName string `json:"status_name" description:"状态名称(中文)"`
|
||||
PaidAt *string `json:"paid_at" description:"支付时间"`
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -90,6 +91,11 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateAgentRechargeReques
|
||||
return nil, errors.New(errors.CodeForbidden, "线下充值仅平台管理员可操作")
|
||||
}
|
||||
|
||||
// 线下充值必须上传支付凭证
|
||||
if req.PaymentMethod == "offline" && strings.TrimSpace(req.PaymentVoucherKey) == "" {
|
||||
return nil, errors.New(errors.CodeInvalidParam, "线下充值必须上传支付凭证")
|
||||
}
|
||||
|
||||
if req.Amount < constants.AgentRechargeMinAmount || req.Amount > constants.AgentRechargeMaxAmount {
|
||||
return nil, errors.New(errors.CodeInvalidParam, "充值金额超出允许范围")
|
||||
}
|
||||
@@ -129,17 +135,18 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateAgentRechargeReques
|
||||
rechargeNo := s.generateRechargeNo()
|
||||
|
||||
record := &model.AgentRechargeRecord{
|
||||
UserID: userID,
|
||||
AgentWalletID: wallet.ID,
|
||||
ShopID: req.ShopID,
|
||||
RechargeNo: rechargeNo,
|
||||
Amount: req.Amount,
|
||||
PaymentMethod: req.PaymentMethod,
|
||||
PaymentChannel: &paymentChannel,
|
||||
PaymentConfigID: paymentConfigID,
|
||||
Status: constants.RechargeStatusPending,
|
||||
ShopIDTag: wallet.ShopIDTag,
|
||||
EnterpriseIDTag: wallet.EnterpriseIDTag,
|
||||
UserID: userID,
|
||||
AgentWalletID: wallet.ID,
|
||||
ShopID: req.ShopID,
|
||||
RechargeNo: rechargeNo,
|
||||
Amount: req.Amount,
|
||||
PaymentMethod: req.PaymentMethod,
|
||||
PaymentChannel: &paymentChannel,
|
||||
PaymentConfigID: paymentConfigID,
|
||||
PaymentVoucherKey: strings.TrimSpace(req.PaymentVoucherKey),
|
||||
Status: constants.RechargeStatusPending,
|
||||
ShopIDTag: wallet.ShopIDTag,
|
||||
EnterpriseIDTag: wallet.EnterpriseIDTag,
|
||||
}
|
||||
|
||||
if err := s.agentRechargeStore.Create(ctx, record); err != nil {
|
||||
@@ -472,17 +479,18 @@ func (s *Service) generateRechargeNo() string {
|
||||
// toResponse 将模型转换为响应 DTO
|
||||
func toResponse(record *model.AgentRechargeRecord, shopName string) *dto.AgentRechargeResponse {
|
||||
resp := &dto.AgentRechargeResponse{
|
||||
ID: record.ID,
|
||||
RechargeNo: record.RechargeNo,
|
||||
ShopID: record.ShopID,
|
||||
ShopName: shopName,
|
||||
AgentWalletID: record.AgentWalletID,
|
||||
Amount: record.Amount,
|
||||
PaymentMethod: record.PaymentMethod,
|
||||
Status: record.Status,
|
||||
StatusName: constants.GetRechargeStatusName(record.Status),
|
||||
CreatedAt: record.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
UpdatedAt: record.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||
ID: record.ID,
|
||||
RechargeNo: record.RechargeNo,
|
||||
ShopID: record.ShopID,
|
||||
ShopName: shopName,
|
||||
AgentWalletID: record.AgentWalletID,
|
||||
Amount: record.Amount,
|
||||
PaymentMethod: record.PaymentMethod,
|
||||
PaymentVoucherKey: record.PaymentVoucherKey,
|
||||
Status: record.Status,
|
||||
StatusName: constants.GetRechargeStatusName(record.Status),
|
||||
CreatedAt: record.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
UpdatedAt: record.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
if record.PaymentChannel != nil {
|
||||
|
||||
Reference in New Issue
Block a user