初始化项目
This commit is contained in:
147
service/order.go
147
service/order.go
@@ -5,31 +5,70 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"order/consts"
|
||||
"order/dao"
|
||||
"order/model/dto"
|
||||
"order/model/entity"
|
||||
)
|
||||
|
||||
// OrderService 订单服务
|
||||
type order struct{}
|
||||
|
||||
type OrderService struct {
|
||||
orderDao *dao.OrderDao
|
||||
// Order 订单服务
|
||||
var Order = new(order)
|
||||
|
||||
// convertOrderItemsFromDTO 从DTO转换订单商品项
|
||||
func convertOrderItemsFromDTO(items []dto.OrderItemReq) []entity.OrderItem {
|
||||
var result []entity.OrderItem
|
||||
for _, item := range items {
|
||||
result = append(result, entity.OrderItem{
|
||||
ProductID: item.ProductID,
|
||||
ProductName: item.ProductName,
|
||||
Price: item.Price,
|
||||
Quantity: item.Quantity,
|
||||
TotalPrice: item.Price * int64(item.Quantity),
|
||||
ImageURL: item.ImageURL,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// NewOrderService 创建订单服务实例
|
||||
func NewOrderService(orderDao *dao.OrderDao) *OrderService {
|
||||
return &OrderService{
|
||||
orderDao: orderDao,
|
||||
// convertOrderItems 转换订单商品项
|
||||
func convertOrderItems(items []entity.OrderItem) []dto.OrderItem {
|
||||
var result []dto.OrderItem
|
||||
for _, item := range items {
|
||||
result = append(result, dto.OrderItem{
|
||||
ProductID: item.ProductID,
|
||||
ProductName: item.ProductName,
|
||||
Price: item.Price,
|
||||
Quantity: item.Quantity,
|
||||
TotalPrice: item.TotalPrice,
|
||||
ImageURL: item.ImageURL,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// convertEntityOrderItemsToDTO 转换entity订单商品项到DTO
|
||||
func convertEntityOrderItemsToDTO(items []entity.OrderItem) []dto.OrderItem {
|
||||
var result []dto.OrderItem
|
||||
for _, item := range items {
|
||||
result = append(result, dto.OrderItem{
|
||||
ProductID: item.ProductID,
|
||||
ProductName: item.ProductName,
|
||||
Price: item.Price,
|
||||
Quantity: item.Quantity,
|
||||
TotalPrice: item.TotalPrice,
|
||||
ImageURL: item.ImageURL,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CreateOrder 创建订单
|
||||
func (s *OrderService) CreateOrder(ctx context.Context, req *dto.CreateOrderReq) (*dto.CreateOrderResp, error) {
|
||||
func (s *order) CreateOrder(ctx context.Context, req *dto.CreateOrderReq) (*dto.CreateOrderResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" || req.UserID == "" || req.Subject == "" {
|
||||
return nil, errors.New("必填参数不能为空")
|
||||
@@ -46,8 +85,8 @@ func (s *OrderService) CreateOrder(ctx context.Context, req *dto.CreateOrderReq)
|
||||
if item.Price <= 0 || item.Quantity <= 0 {
|
||||
return nil, fmt.Errorf("商品价格或数量无效: %s", item.ProductName)
|
||||
}
|
||||
item.TotalPrice = item.Price * int64(item.Quantity)
|
||||
totalAmount += item.TotalPrice
|
||||
totalPrice := item.Price * int64(item.Quantity)
|
||||
totalAmount += totalPrice
|
||||
}
|
||||
|
||||
if totalAmount <= 0 {
|
||||
@@ -73,13 +112,13 @@ func (s *OrderService) CreateOrder(ctx context.Context, req *dto.CreateOrderReq)
|
||||
Description: req.Description,
|
||||
ExpiredAt: &expiredAt,
|
||||
},
|
||||
OrderItems: gconv.Slice[*entity.OrderItem](req.OrderItems),
|
||||
OrderItems: convertOrderItemsFromDTO(req.OrderItems),
|
||||
ShippingInfo: (*entity.ShippingInfo)(&req.ShippingInfo),
|
||||
PayInfo: entity.PayInfo{},
|
||||
}
|
||||
|
||||
// 6. 保存订单
|
||||
if err := s.orderDao.CreatePendingOrder(ctx, order); err != nil {
|
||||
if err := dao.Order.CreatePendingOrder(ctx, order); err != nil {
|
||||
return nil, fmt.Errorf("创建订单失败: %w", err)
|
||||
}
|
||||
|
||||
@@ -95,21 +134,21 @@ func (s *OrderService) CreateOrder(ctx context.Context, req *dto.CreateOrderReq)
|
||||
}
|
||||
|
||||
// generateOrderNo 生成订单号
|
||||
func (s *OrderService) generateOrderNo(tenantID string) string {
|
||||
func (s *order) generateOrderNo(tenantID string) string {
|
||||
timestamp := time.Now().Format("20060102150405")
|
||||
random := rand.Intn(10000)
|
||||
return fmt.Sprintf("%s%s%04d", tenantID, timestamp, random)
|
||||
}
|
||||
|
||||
// QueryOrder 查询订单详情
|
||||
func (s *OrderService) QueryOrder(ctx context.Context, req *dto.QueryOrderReq) (*dto.QueryOrderResp, error) {
|
||||
func (s *order) QueryOrder(ctx context.Context, req *dto.QueryOrderReq) (*dto.QueryOrderResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" || req.OrderNo == "" {
|
||||
return nil, errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询订单
|
||||
order, status, err := s.orderDao.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
order, status, err := dao.Order.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||
}
|
||||
@@ -122,19 +161,19 @@ func (s *OrderService) QueryOrder(ctx context.Context, req *dto.QueryOrderReq) (
|
||||
var resp dto.QueryOrderResp
|
||||
|
||||
switch status {
|
||||
case entity.OrderStatusPending:
|
||||
case consts.OrderStatusPending:
|
||||
if pendingOrder, ok := order.(*entity.OrderPending); ok {
|
||||
resp.Order = s.convertPendingOrderToDetail(pendingOrder)
|
||||
}
|
||||
case entity.OrderStatusPaid:
|
||||
case consts.OrderStatusPaid:
|
||||
if paidOrder, ok := order.(*entity.OrderPaid); ok {
|
||||
resp.Order = s.convertPaidOrderToDetail(paidOrder)
|
||||
}
|
||||
case entity.OrderStatusShipped:
|
||||
case consts.OrderStatusShipped:
|
||||
if shippedOrder, ok := order.(*entity.OrderShipped); ok {
|
||||
resp.Order = s.convertShippedOrderToDetail(shippedOrder)
|
||||
}
|
||||
case entity.OrderStatusCompleted:
|
||||
case consts.OrderStatusCompleted:
|
||||
if completedOrder, ok := order.(*entity.OrderCompleted); ok {
|
||||
resp.Order = s.convertCompletedOrderToDetail(completedOrder)
|
||||
}
|
||||
@@ -146,7 +185,7 @@ func (s *OrderService) QueryOrder(ctx context.Context, req *dto.QueryOrderReq) (
|
||||
}
|
||||
|
||||
// convertPendingOrderToDetail 转换待支付订单为详情
|
||||
func (s *OrderService) convertPendingOrderToDetail(order *entity.OrderPending) dto.OrderDetail {
|
||||
func (s *order) convertPendingOrderToDetail(order *entity.OrderPending) dto.OrderDetail {
|
||||
return dto.OrderDetail{
|
||||
ID: order.ID.Hex(),
|
||||
TenantID: order.TenantID,
|
||||
@@ -154,13 +193,13 @@ func (s *OrderService) convertPendingOrderToDetail(order *entity.OrderPending) d
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
Status: string(entity.OrderStatusPending),
|
||||
Status: string(consts.OrderStatusPending),
|
||||
PayMethod: order.PayMethod,
|
||||
PayStatus: "unpaid",
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
||||
OrderItems: convertOrderItems(order.OrderItems),
|
||||
ShippingInfo: dto.ShippingInfo{
|
||||
Consignee: order.ShippingInfo.Consignee,
|
||||
Phone: order.ShippingInfo.Phone,
|
||||
@@ -183,7 +222,7 @@ func (s *OrderService) convertPendingOrderToDetail(order *entity.OrderPending) d
|
||||
}
|
||||
|
||||
// convertPaidOrderToDetail 转换已支付订单为详情
|
||||
func (s *OrderService) convertPaidOrderToDetail(order *entity.OrderPaid) dto.OrderDetail {
|
||||
func (s *order) convertPaidOrderToDetail(order *entity.OrderPaid) dto.OrderDetail {
|
||||
return dto.OrderDetail{
|
||||
ID: order.ID.Hex(),
|
||||
TenantID: order.TenantID,
|
||||
@@ -191,13 +230,13 @@ func (s *OrderService) convertPaidOrderToDetail(order *entity.OrderPaid) dto.Ord
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
Status: string(entity.OrderStatusPaid),
|
||||
Status: string(consts.OrderStatusPaid),
|
||||
PayMethod: order.PayMethod,
|
||||
PayStatus: "paid",
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
||||
OrderItems: convertOrderItems(order.OrderItems),
|
||||
ShippingInfo: dto.ShippingInfo{
|
||||
Consignee: order.ShippingInfo.Consignee,
|
||||
Phone: order.ShippingInfo.Phone,
|
||||
@@ -218,7 +257,7 @@ func (s *OrderService) convertPaidOrderToDetail(order *entity.OrderPaid) dto.Ord
|
||||
}
|
||||
|
||||
// convertShippedOrderToDetail 转换已发货订单为详情
|
||||
func (s *OrderService) convertShippedOrderToDetail(order *entity.OrderShipped) dto.OrderDetail {
|
||||
func (s *order) convertShippedOrderToDetail(order *entity.OrderShipped) dto.OrderDetail {
|
||||
return dto.OrderDetail{
|
||||
ID: order.ID.Hex(),
|
||||
TenantID: order.TenantID,
|
||||
@@ -226,13 +265,13 @@ func (s *OrderService) convertShippedOrderToDetail(order *entity.OrderShipped) d
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
Status: string(entity.OrderStatusShipped),
|
||||
Status: string(consts.OrderStatusShipped),
|
||||
PayMethod: order.PayMethod,
|
||||
PayStatus: "paid",
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
||||
OrderItems: convertOrderItems(order.OrderItems),
|
||||
ShippingInfo: dto.ShippingInfo{
|
||||
Consignee: order.ShippingInfo.Consignee,
|
||||
Phone: order.ShippingInfo.Phone,
|
||||
@@ -249,7 +288,7 @@ func (s *OrderService) convertShippedOrderToDetail(order *entity.OrderShipped) d
|
||||
}
|
||||
|
||||
// convertCompletedOrderToDetail 转换已完成订单为详情
|
||||
func (s *OrderService) convertCompletedOrderToDetail(order *entity.OrderCompleted) dto.OrderDetail {
|
||||
func (s *order) convertCompletedOrderToDetail(order *entity.OrderCompleted) dto.OrderDetail {
|
||||
return dto.OrderDetail{
|
||||
ID: order.ID.Hex(),
|
||||
TenantID: order.TenantID,
|
||||
@@ -257,13 +296,13 @@ func (s *OrderService) convertCompletedOrderToDetail(order *entity.OrderComplete
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
Status: string(entity.OrderStatusCompleted),
|
||||
Status: string(consts.OrderStatusCompleted),
|
||||
PayMethod: order.PayMethod,
|
||||
PayStatus: "paid",
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
||||
OrderItems: convertOrderItems(order.OrderItems),
|
||||
ShippingInfo: dto.ShippingInfo{
|
||||
Consignee: order.ShippingInfo.Consignee,
|
||||
Phone: order.ShippingInfo.Phone,
|
||||
@@ -280,7 +319,7 @@ func (s *OrderService) convertCompletedOrderToDetail(order *entity.OrderComplete
|
||||
}
|
||||
|
||||
// convertOrderItems 转换订单商品项
|
||||
func (s *OrderService) convertOrderItems(items []*entity.OrderItem) []dto.OrderItem {
|
||||
func (s *order) convertOrderItems(items []*entity.OrderItem) []dto.OrderItem {
|
||||
var result []dto.OrderItem
|
||||
for _, item := range items {
|
||||
result = append(result, dto.OrderItem{
|
||||
@@ -296,14 +335,14 @@ func (s *OrderService) convertOrderItems(items []*entity.OrderItem) []dto.OrderI
|
||||
}
|
||||
|
||||
// CancelOrder 取消订单
|
||||
func (s *OrderService) CancelOrder(ctx context.Context, req *dto.CancelOrderReq) (*dto.CancelOrderResp, error) {
|
||||
func (s *order) CancelOrder(ctx context.Context, req *dto.CancelOrderReq) (*dto.CancelOrderResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" || req.OrderNo == "" {
|
||||
return nil, errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询订单
|
||||
order, status, err := s.orderDao.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
order, status, err := dao.Order.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||
}
|
||||
@@ -313,7 +352,7 @@ func (s *OrderService) CancelOrder(ctx context.Context, req *dto.CancelOrderReq)
|
||||
}
|
||||
|
||||
// 3. 检查订单状态(只有待支付订单可以取消)
|
||||
if status != entity.OrderStatusPending {
|
||||
if status != consts.OrderStatusPending {
|
||||
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
||||
}
|
||||
|
||||
@@ -322,21 +361,21 @@ func (s *OrderService) CancelOrder(ctx context.Context, req *dto.CancelOrderReq)
|
||||
"cancel_reason": req.Reason,
|
||||
}
|
||||
|
||||
if err := s.orderDao.MoveOrderToStatus(ctx, entity.OrderStatusPending, entity.OrderStatusCancelled, req.TenantID, req.OrderNo, updateData); err != nil {
|
||||
if err := dao.Order.MoveOrderToStatus(ctx, consts.OrderStatusPending, consts.OrderStatusCancelled, req.TenantID, req.OrderNo, updateData); err != nil {
|
||||
return nil, fmt.Errorf("取消订单失败: %w", err)
|
||||
}
|
||||
|
||||
// 5. 返回结果
|
||||
resp := &dto.CancelOrderResp{
|
||||
OrderNo: req.OrderNo,
|
||||
Status: string(entity.OrderStatusCancelled),
|
||||
Status: string(consts.OrderStatusCancelled),
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ListOrders 查询订单列表
|
||||
func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (*dto.ListOrdersResp, error) {
|
||||
func (s *order) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (*dto.ListOrdersResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" {
|
||||
return nil, errors.New("租户ID不能为空")
|
||||
@@ -350,15 +389,15 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
||||
}
|
||||
|
||||
// 2. 根据状态查询订单列表
|
||||
var status entity.OrderStatus
|
||||
var status consts.OrderStatus
|
||||
if req.Status != "" {
|
||||
status = entity.OrderStatus(req.Status)
|
||||
status = consts.OrderStatus(req.Status)
|
||||
} else {
|
||||
// 默认查询所有状态
|
||||
status = entity.OrderStatusPending
|
||||
status = consts.OrderStatusPending
|
||||
}
|
||||
|
||||
orders, total, err := s.orderDao.ListOrdersByStatus(ctx, status, req.TenantID, req.UserID, req.Page, req.PageSize)
|
||||
orders, total, err := dao.Order.ListOrdersByStatus(ctx, status, req.TenantID, req.UserID, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询订单列表失败: %w", err)
|
||||
}
|
||||
@@ -367,7 +406,7 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
||||
var orderSummaries []dto.OrderSummary
|
||||
|
||||
switch status {
|
||||
case entity.OrderStatusPending:
|
||||
case consts.OrderStatusPending:
|
||||
if pendingOrders, ok := orders.([]entity.OrderPending); ok {
|
||||
for _, order := range pendingOrders {
|
||||
orderSummaries = append(orderSummaries, dto.OrderSummary{
|
||||
@@ -375,13 +414,13 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
||||
OrderNo: order.OrderNo,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
Status: string(entity.OrderStatusPending),
|
||||
Status: string(consts.OrderStatusPending),
|
||||
Subject: order.Subject,
|
||||
CreatedAt: order.CreatedAt,
|
||||
})
|
||||
}
|
||||
}
|
||||
case entity.OrderStatusPaid:
|
||||
case consts.OrderStatusPaid:
|
||||
if paidOrders, ok := orders.([]entity.OrderPaid); ok {
|
||||
for _, order := range paidOrders {
|
||||
orderSummaries = append(orderSummaries, dto.OrderSummary{
|
||||
@@ -389,7 +428,7 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
||||
OrderNo: order.OrderNo,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
Status: string(entity.OrderStatusPaid),
|
||||
Status: string(consts.OrderStatusPaid),
|
||||
Subject: order.Subject,
|
||||
CreatedAt: order.CreatedAt,
|
||||
PaidAt: &order.PaidAt,
|
||||
@@ -411,9 +450,9 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
||||
}
|
||||
|
||||
// ProcessExpiredOrders 处理过期订单
|
||||
func (s *OrderService) ProcessExpiredOrders(ctx context.Context, tenantID string) error {
|
||||
func (s *order) ProcessExpiredOrders(ctx context.Context, tenantID string) error {
|
||||
// 获取过期的待支付订单
|
||||
expiredOrders, err := s.orderDao.GetExpiredPendingOrders(ctx, tenantID)
|
||||
expiredOrders, err := dao.Order.GetExpiredPendingOrders(ctx, tenantID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取过期订单失败: %w", err)
|
||||
}
|
||||
@@ -424,7 +463,7 @@ func (s *OrderService) ProcessExpiredOrders(ctx context.Context, tenantID string
|
||||
"cancel_reason": "订单超时自动取消",
|
||||
}
|
||||
|
||||
if err := s.orderDao.MoveOrderToStatus(ctx, entity.OrderStatusPending, entity.OrderStatusCancelled, tenantID, order.OrderNo, updateData); err != nil {
|
||||
if err := dao.Order.MoveOrderToStatus(ctx, consts.OrderStatusPending, consts.OrderStatusCancelled, tenantID, order.OrderNo, updateData); err != nil {
|
||||
// 记录错误但继续处理其他订单
|
||||
fmt.Printf("取消过期订单失败: %s, 错误: %v\n", order.OrderNo, err)
|
||||
}
|
||||
@@ -434,6 +473,6 @@ func (s *OrderService) ProcessExpiredOrders(ctx context.Context, tenantID string
|
||||
}
|
||||
|
||||
// UpdatePayInfo 更新支付信息
|
||||
func (s *OrderService) UpdatePayInfo(ctx context.Context, tenantID, orderNo string, payInfo entity.PayInfo) error {
|
||||
return s.orderDao.UpdatePayInfo(ctx, tenantID, orderNo, payInfo)
|
||||
func (s *order) UpdatePayInfo(ctx context.Context, tenantID, orderNo string, payInfo entity.PayInfo) error {
|
||||
return dao.Order.UpdatePayInfo(ctx, tenantID, orderNo, payInfo)
|
||||
}
|
||||
|
||||
@@ -7,45 +7,27 @@ import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"order/consts"
|
||||
"order/dao"
|
||||
"order/model/dto"
|
||||
"order/model/entity"
|
||||
)
|
||||
|
||||
// PaymentService 支付服务
|
||||
type payment struct{}
|
||||
|
||||
type PaymentService struct {
|
||||
orderDao *dao.OrderDao
|
||||
paymentConfigDao *dao.PaymentConfigDao
|
||||
paymentRecordDao *dao.PaymentRecordDao
|
||||
refundRecordDao *dao.RefundRecordDao
|
||||
}
|
||||
|
||||
// NewPaymentService 创建支付服务实例
|
||||
func NewPaymentService(
|
||||
orderDao *dao.OrderDao,
|
||||
paymentConfigDao *dao.PaymentConfigDao,
|
||||
paymentRecordDao *dao.PaymentRecordDao,
|
||||
refundRecordDao *dao.RefundRecordDao,
|
||||
) *PaymentService {
|
||||
return &PaymentService{
|
||||
orderDao: orderDao,
|
||||
paymentConfigDao: paymentConfigDao,
|
||||
paymentRecordDao: paymentRecordDao,
|
||||
refundRecordDao: refundRecordDao,
|
||||
}
|
||||
}
|
||||
// Payment 支付服务
|
||||
var Payment = new(payment)
|
||||
|
||||
// PayOrder 支付订单
|
||||
func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*dto.PayOrderResp, error) {
|
||||
func (s *payment) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*dto.PayOrderResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" || req.OrderNo == "" || req.PayMethod == "" || req.PayType == "" {
|
||||
return nil, errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询订单
|
||||
order, status, err := s.orderDao.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
order, status, err := dao.Order.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||
}
|
||||
@@ -55,7 +37,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
||||
}
|
||||
|
||||
// 3. 验证订单状态(只有待支付订单可以支付)
|
||||
if status != entity.OrderStatusPending {
|
||||
if status != consts.OrderStatusPending {
|
||||
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
||||
}
|
||||
|
||||
@@ -65,7 +47,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
||||
}
|
||||
|
||||
// 4. 获取支付配置
|
||||
paymentConfig, err := s.paymentConfigDao.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
|
||||
paymentConfig, err := dao.PaymentConfig.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取支付配置失败: %w", err)
|
||||
}
|
||||
@@ -92,7 +74,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
||||
Status: "pending",
|
||||
}
|
||||
|
||||
if err := s.paymentRecordDao.Create(ctx, paymentRecord); err != nil {
|
||||
if err := dao.PaymentRecord.Create(ctx, paymentRecord); err != nil {
|
||||
return nil, fmt.Errorf("创建支付记录失败: %w", err)
|
||||
}
|
||||
|
||||
@@ -106,7 +88,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
||||
APPParams: payResp.APPParams,
|
||||
}
|
||||
|
||||
if err := s.orderDao.UpdatePayInfo(ctx, req.TenantID, req.OrderNo, payInfo); err != nil {
|
||||
if err := dao.Order.UpdatePayInfo(ctx, req.TenantID, req.OrderNo, payInfo); err != nil {
|
||||
return nil, fmt.Errorf("更新订单支付信息失败: %w", err)
|
||||
}
|
||||
|
||||
@@ -124,7 +106,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
||||
}
|
||||
|
||||
// callThirdPartyPayment 调用第三方支付接口
|
||||
func (s *PaymentService) callThirdPartyPayment(ctx context.Context, config *entity.PaymentConfig, req *dto.PayOrderReq, order *entity.OrderPending) (*PaymentResponse, error) {
|
||||
func (s *payment) callThirdPartyPayment(ctx context.Context, config *entity.PaymentConfig, req *dto.PayOrderReq, order *entity.OrderPending) (*PaymentResponse, error) {
|
||||
// 这里应该是实际的第三方支付接口调用
|
||||
// 为了演示,我们返回模拟数据
|
||||
|
||||
@@ -168,14 +150,14 @@ type PaymentResponse struct {
|
||||
}
|
||||
|
||||
// generateOutTradeNo 生成商户订单号
|
||||
func (s *PaymentService) generateOutTradeNo(tenantID string) string {
|
||||
func (s *payment) generateOutTradeNo(tenantID string) string {
|
||||
timestamp := time.Now().Format("20060102150405")
|
||||
random := rand.Intn(10000)
|
||||
return fmt.Sprintf("%s%s%04d", tenantID, timestamp, random)
|
||||
}
|
||||
|
||||
// generateNonceStr 生成随机字符串
|
||||
func (s *PaymentService) generateNonceStr() string {
|
||||
func (s *payment) generateNonceStr() string {
|
||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
b := make([]byte, 16)
|
||||
for i := range b {
|
||||
@@ -185,14 +167,14 @@ func (s *PaymentService) generateNonceStr() string {
|
||||
}
|
||||
|
||||
// HandlePaymentNotify 处理支付回调
|
||||
func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNotifyReq) error {
|
||||
func (s *payment) HandlePaymentNotify(ctx context.Context, req *dto.PaymentNotifyReq) error {
|
||||
// 1. 验证回调签名
|
||||
if !s.verifyNotifySignature(req) {
|
||||
return errors.New("签名验证失败")
|
||||
}
|
||||
|
||||
// 2. 查询支付记录
|
||||
paymentRecord, err := s.paymentRecordDao.GetByOrderNo(ctx, req.TenantID, req.OrderNo)
|
||||
paymentRecord, err := dao.PaymentRecord.GetByOrderNo(ctx, req.TenantID, req.OrderNo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询支付记录失败: %w", err)
|
||||
}
|
||||
@@ -202,7 +184,7 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
|
||||
}
|
||||
|
||||
// 3. 更新支付记录状态
|
||||
if err := s.paymentRecordDao.UpdateStatus(ctx, paymentRecord.ID.Hex(), req.Status, req.TransactionID, req.TradeNo); err != nil {
|
||||
if err := dao.PaymentRecord.UpdateStatus(ctx, paymentRecord.ID.Hex(), req.Status, req.TransactionID, req.TradeNo); err != nil {
|
||||
return fmt.Errorf("更新支付记录失败: %w", err)
|
||||
}
|
||||
|
||||
@@ -215,7 +197,7 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
|
||||
"payment_channel": req.PayMethod,
|
||||
}
|
||||
|
||||
if err := s.orderDao.MoveOrderToStatus(ctx, entity.OrderStatusPending, entity.OrderStatusPaid, req.TenantID, req.OrderNo, updateData); err != nil {
|
||||
if err := dao.Order.MoveOrderToStatus(ctx, consts.OrderStatusPending, consts.OrderStatusPaid, req.TenantID, req.OrderNo, updateData); err != nil {
|
||||
return fmt.Errorf("更新订单状态失败: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -223,34 +205,22 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
|
||||
return nil
|
||||
}
|
||||
|
||||
// PaymentNotifyReq 支付回调请求
|
||||
|
||||
type PaymentNotifyReq struct {
|
||||
TenantID string `json:"tenant_id"` // 租户ID
|
||||
OrderNo string `json:"order_no"` // 订单号
|
||||
PayMethod string `json:"pay_method"` // 支付方式
|
||||
Status string `json:"status"` // 支付状态
|
||||
TransactionID string `json:"transaction_id"` // 交易号
|
||||
TradeNo string `json:"trade_no"` // 交易号
|
||||
Sign string `json:"sign"` // 签名
|
||||
}
|
||||
|
||||
// verifyNotifySignature 验证回调签名
|
||||
func (s *PaymentService) verifyNotifySignature(req *PaymentNotifyReq) bool {
|
||||
func (s *payment) verifyNotifySignature(req *dto.PaymentNotifyReq) bool {
|
||||
// 这里应该是实际的签名验证逻辑
|
||||
// 为了演示,我们总是返回true
|
||||
return true
|
||||
}
|
||||
|
||||
// RefundOrder 退款
|
||||
func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderReq) (*dto.RefundOrderResp, error) {
|
||||
func (s *payment) RefundOrder(ctx context.Context, req *dto.RefundOrderReq) (*dto.RefundOrderResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" || req.OrderNo == "" || req.RefundAmount <= 0 {
|
||||
return nil, errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询订单
|
||||
order, status, err := s.orderDao.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
order, status, err := dao.Order.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||
}
|
||||
@@ -260,7 +230,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
||||
}
|
||||
|
||||
// 3. 验证订单状态(只有已支付订单可以退款)
|
||||
if status != entity.OrderStatusPaid {
|
||||
if status != consts.OrderStatusPaid {
|
||||
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
||||
}
|
||||
|
||||
@@ -291,7 +261,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
||||
Status: "pending",
|
||||
}
|
||||
|
||||
if err := s.refundRecordDao.Create(ctx, refundRecord); err != nil {
|
||||
if err := dao.RefundRecord.Create(ctx, refundRecord); err != nil {
|
||||
return nil, fmt.Errorf("创建退款记录失败: %w", err)
|
||||
}
|
||||
|
||||
@@ -301,7 +271,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
||||
"refund_reason": req.Reason,
|
||||
}
|
||||
|
||||
if err := s.orderDao.MoveOrderToStatus(ctx, entity.OrderStatusPaid, entity.OrderStatusRefunded, req.TenantID, req.OrderNo, updateData); err != nil {
|
||||
if err := dao.Order.MoveOrderToStatus(ctx, consts.OrderStatusPaid, consts.OrderStatusRefunded, req.TenantID, req.OrderNo, updateData); err != nil {
|
||||
return nil, fmt.Errorf("更新订单状态失败: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -317,7 +287,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
||||
}
|
||||
|
||||
// callThirdPartyRefund 调用第三方退款接口
|
||||
func (s *PaymentService) callThirdPartyRefund(ctx context.Context, req *dto.RefundOrderReq, order *entity.OrderPaid) (*RefundResponse, error) {
|
||||
func (s *payment) callThirdPartyRefund(ctx context.Context, req *dto.RefundOrderReq, order *entity.OrderPaid) (*RefundResponse, error) {
|
||||
// 这里应该是实际的第三方退款接口调用
|
||||
// 为了演示,我们返回模拟数据
|
||||
|
||||
@@ -338,21 +308,21 @@ type RefundResponse struct {
|
||||
}
|
||||
|
||||
// generateRefundNo 生成退款单号
|
||||
func (s *PaymentService) generateRefundNo(tenantID string) string {
|
||||
func (s *payment) generateRefundNo(tenantID string) string {
|
||||
timestamp := time.Now().Format("20060102150405")
|
||||
random := rand.Intn(10000)
|
||||
return fmt.Sprintf("R%s%s%04d", tenantID, timestamp, random)
|
||||
}
|
||||
|
||||
// HandleRefundNotify 处理退款回调
|
||||
func (s *PaymentService) HandleRefundNotify(ctx context.Context, req *RefundNotifyReq) error {
|
||||
func (s *payment) HandleRefundNotify(ctx context.Context, req *dto.RefundNotifyReq) error {
|
||||
// 1. 验证回调签名
|
||||
if !s.verifyRefundNotifySignature(req) {
|
||||
return errors.New("签名验证失败")
|
||||
}
|
||||
|
||||
// 2. 查询退款记录
|
||||
refundRecord, err := s.refundRecordDao.GetByRefundNo(ctx, req.TenantID, req.RefundNo)
|
||||
refundRecord, err := dao.RefundRecord.GetByRefundNo(ctx, req.TenantID, req.RefundNo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询退款记录失败: %w", err)
|
||||
}
|
||||
@@ -362,25 +332,15 @@ func (s *PaymentService) HandleRefundNotify(ctx context.Context, req *RefundNoti
|
||||
}
|
||||
|
||||
// 3. 更新退款记录状态
|
||||
if err := s.refundRecordDao.UpdateRefundStatus(ctx, refundRecord.ID.Hex(), req.Status, req.RefundID); err != nil {
|
||||
if err := dao.RefundRecord.UpdateRefundStatus(ctx, refundRecord.ID.Hex(), req.Status, req.RefundID); err != nil {
|
||||
return fmt.Errorf("更新退款记录失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RefundNotifyReq 退款回调请求
|
||||
|
||||
type RefundNotifyReq struct {
|
||||
TenantID string `json:"tenant_id"` // 租户ID
|
||||
RefundNo string `json:"refund_no"` // 退款单号
|
||||
Status string `json:"status"` // 退款状态
|
||||
RefundID string `json:"refund_id"` // 退款ID
|
||||
Sign string `json:"sign"` // 签名
|
||||
}
|
||||
|
||||
// verifyRefundNotifySignature 验证退款回调签名
|
||||
func (s *PaymentService) verifyRefundNotifySignature(req *RefundNotifyReq) bool {
|
||||
func (s *payment) verifyRefundNotifySignature(req *dto.RefundNotifyReq) bool {
|
||||
// 这里应该是实际的签名验证逻辑
|
||||
// 为了演示,我们总是返回true
|
||||
return true
|
||||
|
||||
436
service/payment_config.go
Normal file
436
service/payment_config.go
Normal file
@@ -0,0 +1,436 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"order/dao"
|
||||
"order/model/dto"
|
||||
"order/model/entity"
|
||||
)
|
||||
|
||||
type paymentConfig struct{}
|
||||
|
||||
// PaymentConfig 支付配置服务
|
||||
var PaymentConfig = new(paymentConfig)
|
||||
|
||||
// CreatePaymentConfig 创建支付配置
|
||||
func (s *paymentConfig) CreatePaymentConfig(ctx context.Context, req *dto.CreatePaymentConfigReq) (*dto.PaymentConfigResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" || req.PayMethod == "" {
|
||||
return nil, errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 检查支付方式是否已存在
|
||||
exist, err := dao.PaymentConfig.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exist != nil {
|
||||
return nil, errors.New("该支付方式已存在配置")
|
||||
}
|
||||
|
||||
// 3. 创建配置实体
|
||||
config := parseConfigMap(req.PayMethod, req.Config)
|
||||
config.TenantID = req.TenantID
|
||||
config.Description = req.Remark
|
||||
config.Enabled = req.IsEnabled
|
||||
|
||||
// 4. 保存配置
|
||||
if err := dao.PaymentConfig.Create(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 5. 返回结果
|
||||
resp := &dto.PaymentConfigResp{
|
||||
ID: config.ID.Hex(),
|
||||
TenantID: config.TenantID,
|
||||
PayMethod: config.PayMethod,
|
||||
Config: buildConfigMap(config),
|
||||
IsEnabled: config.Enabled,
|
||||
Remark: config.Description,
|
||||
CreatedAt: time.Now(), // 暂时使用当前时间
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// UpdatePaymentConfig 更新支付配置
|
||||
func (s *paymentConfig) UpdatePaymentConfig(ctx context.Context, req *dto.UpdatePaymentConfigReq) (*dto.PaymentConfigResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.ID == "" || req.TenantID == "" {
|
||||
return nil, errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询配置
|
||||
objectID, err := bson.ObjectIDFromHex(req.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("无效的配置ID")
|
||||
}
|
||||
|
||||
config, err := dao.PaymentConfig.GetByID(ctx, objectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if config == nil {
|
||||
return nil, errors.New("支付配置不存在")
|
||||
}
|
||||
|
||||
// 3. 检查是否是租户自己的配置
|
||||
if config.TenantID != req.TenantID {
|
||||
return nil, errors.New("无权限操作该配置")
|
||||
}
|
||||
|
||||
// 4. 更新配置实体
|
||||
config.ConfigName = req.ConfigName
|
||||
config.Description = req.Remark
|
||||
config.Enabled = req.IsEnabled
|
||||
|
||||
// 解析配置参数
|
||||
parseConfigMapToEntity(config.PayMethod, req.Config, config)
|
||||
|
||||
// 5. 更新配置
|
||||
if err := dao.PaymentConfig.Update(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 6. 返回结果
|
||||
resp := &dto.PaymentConfigResp{
|
||||
ID: config.ID.Hex(),
|
||||
TenantID: config.TenantID,
|
||||
PayMethod: config.PayMethod,
|
||||
ConfigName: config.ConfigName,
|
||||
Remark: config.Description,
|
||||
IsEnabled: config.Enabled,
|
||||
Config: convertEntityToConfigMap(config),
|
||||
CreatedAt: time.Unix(0, 0), // 实体中没有时间字段,使用默认值
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetPaymentConfig 获取支付配置
|
||||
func (s *paymentConfig) GetPaymentConfig(ctx context.Context, req *dto.QueryPaymentConfigReq) (*dto.PaymentConfigResp, error) {
|
||||
// 1. 参数验证
|
||||
if req.TenantID == "" {
|
||||
return nil, errors.New("租户ID不能为空")
|
||||
}
|
||||
|
||||
var config *entity.PaymentConfig
|
||||
var err error
|
||||
|
||||
// 2. 查询配置
|
||||
if req.PayMethod != "" {
|
||||
// 按租户和支付方式查询
|
||||
config, err = dao.PaymentConfig.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
|
||||
} else {
|
||||
// 只按租户查询(获取所有支付方式配置)
|
||||
configs, err := dao.PaymentConfig.GetByTenantID(ctx, req.TenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(configs) > 0 {
|
||||
config = &configs[0] // 返回第一个配置作为默认
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if config == nil {
|
||||
return nil, errors.New("支付配置不存在")
|
||||
}
|
||||
|
||||
// 3. 返回结果
|
||||
resp := &dto.PaymentConfigResp{
|
||||
ID: config.ID.Hex(),
|
||||
TenantID: config.TenantID,
|
||||
PayMethod: config.PayMethod,
|
||||
ConfigName: config.ConfigName,
|
||||
Remark: config.Description,
|
||||
IsEnabled: config.Enabled,
|
||||
Config: convertEntityToConfigMap(config),
|
||||
CreatedAt: time.Unix(0, 0),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetPaymentConfigList 获取支付配置列表
|
||||
func (s *paymentConfig) GetPaymentConfigList(ctx context.Context, tenantID string) ([]dto.PaymentConfigResp, error) {
|
||||
// 1. 参数验证
|
||||
if tenantID == "" {
|
||||
return nil, errors.New("租户ID不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询配置列表
|
||||
configs, err := dao.PaymentConfig.GetByTenantID(ctx, tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 转换为响应格式
|
||||
var resp []dto.PaymentConfigResp
|
||||
for _, config := range configs {
|
||||
resp = append(resp, dto.PaymentConfigResp{
|
||||
ID: config.ID.Hex(),
|
||||
TenantID: config.TenantID,
|
||||
PayMethod: config.PayMethod,
|
||||
ConfigName: config.ConfigName,
|
||||
Remark: config.Description,
|
||||
IsEnabled: config.Enabled,
|
||||
Config: convertEntityToConfigMap(&config),
|
||||
CreatedAt: time.Unix(0, 0),
|
||||
UpdatedAt: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DeletePaymentConfig 删除支付配置
|
||||
func (s *paymentConfig) DeletePaymentConfig(ctx context.Context, tenantID, configID string) error {
|
||||
// 1. 参数验证
|
||||
if tenantID == "" || configID == "" {
|
||||
return errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询配置
|
||||
objectID, err := bson.ObjectIDFromHex(configID)
|
||||
if err != nil {
|
||||
return errors.New("无效的配置ID")
|
||||
}
|
||||
|
||||
config, err := dao.PaymentConfig.GetByID(ctx, objectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if config == nil {
|
||||
return errors.New("支付配置不存在")
|
||||
}
|
||||
|
||||
// 3. 检查是否是租户自己的配置
|
||||
if config.TenantID != tenantID {
|
||||
return errors.New("无权限操作该配置")
|
||||
}
|
||||
|
||||
// 4. 删除配置
|
||||
return dao.PaymentConfig.Delete(ctx, objectID)
|
||||
}
|
||||
|
||||
// EnablePaymentConfig 启用支付配置
|
||||
func (s *paymentConfig) EnablePaymentConfig(ctx context.Context, tenantID, configID string) error {
|
||||
return s.updateConfigStatus(ctx, tenantID, configID, true)
|
||||
}
|
||||
|
||||
// DisablePaymentConfig 禁用支付配置
|
||||
func (s *paymentConfig) DisablePaymentConfig(ctx context.Context, tenantID, configID string) error {
|
||||
return s.updateConfigStatus(ctx, tenantID, configID, false)
|
||||
}
|
||||
|
||||
// updateConfigStatus 更新配置状态
|
||||
func (s *paymentConfig) updateConfigStatus(ctx context.Context, tenantID, configID string, enabled bool) error {
|
||||
// 1. 参数验证
|
||||
if tenantID == "" || configID == "" {
|
||||
return errors.New("必填参数不能为空")
|
||||
}
|
||||
|
||||
// 2. 查询配置
|
||||
objectID, err := bson.ObjectIDFromHex(configID)
|
||||
if err != nil {
|
||||
return errors.New("无效的配置ID")
|
||||
}
|
||||
|
||||
config, err := dao.PaymentConfig.GetByID(ctx, objectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if config == nil {
|
||||
return errors.New("支付配置不存在")
|
||||
}
|
||||
|
||||
// 3. 检查是否是租户自己的配置
|
||||
if config.TenantID != tenantID {
|
||||
return errors.New("无权限操作该配置")
|
||||
}
|
||||
|
||||
// 4. 更新状态
|
||||
config.Enabled = enabled
|
||||
|
||||
return dao.PaymentConfig.Update(ctx, config)
|
||||
}
|
||||
|
||||
// WechatConfig 微信支付配置服务
|
||||
var WechatConfig = new(wechatConfig)
|
||||
|
||||
type wechatConfig struct{}
|
||||
|
||||
// GetWechatConfig 获取微信支付配置
|
||||
func (s *wechatConfig) GetWechatConfig(ctx context.Context, tenantID string) (*dto.WechatConfig, error) {
|
||||
// 1. 获取微信支付配置
|
||||
resp, err := PaymentConfig.GetPaymentConfig(ctx, &dto.QueryPaymentConfigReq{
|
||||
TenantID: tenantID,
|
||||
PayMethod: "wechat",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. 转换为微信配置结构体
|
||||
configMap := resp.Config
|
||||
|
||||
wechatConfig := &dto.WechatConfig{
|
||||
ID: resp.ID,
|
||||
TenantID: resp.TenantID,
|
||||
ConfigName: resp.ConfigName,
|
||||
AppID: getString(configMap, "app_id"),
|
||||
MchID: getString(configMap, "mch_id"),
|
||||
APIKey: getString(configMap, "api_key"),
|
||||
NotifyURL: getString(configMap, "notify_url"),
|
||||
ReturnURL: getString(configMap, "return_url"),
|
||||
CertPath: getString(configMap, "cert_path"),
|
||||
KeyPath: getString(configMap, "key_path"),
|
||||
Sandbox: getBool(configMap, "sandbox"),
|
||||
GatewayURL: getString(configMap, "gateway_url"),
|
||||
SupportNative: getBool(configMap, "support_native"),
|
||||
SupportJSAPI: getBool(configMap, "support_jsapi"),
|
||||
SupportAPP: getBool(configMap, "support_app"),
|
||||
SupportH5: getBool(configMap, "support_h5"),
|
||||
}
|
||||
|
||||
return wechatConfig, nil
|
||||
}
|
||||
|
||||
// AlipayConfig 支付宝支付配置服务
|
||||
var AlipayConfig = new(alipayConfig)
|
||||
|
||||
type alipayConfig struct{}
|
||||
|
||||
// GetAlipayConfig 获取支付宝支付配置
|
||||
func (s *alipayConfig) GetAlipayConfig(ctx context.Context, tenantID string) (*dto.AlipayConfig, error) {
|
||||
// 1. 获取支付宝支付配置
|
||||
resp, err := PaymentConfig.GetPaymentConfig(ctx, &dto.QueryPaymentConfigReq{
|
||||
TenantID: tenantID,
|
||||
PayMethod: "alipay",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. 转换为支付宝配置结构体
|
||||
configMap := resp.Config
|
||||
|
||||
alipayConfig := &dto.AlipayConfig{
|
||||
ID: resp.ID,
|
||||
TenantID: resp.TenantID,
|
||||
ConfigName: resp.ConfigName,
|
||||
AppID: getString(configMap, "app_id"),
|
||||
NotifyURL: getString(configMap, "notify_url"),
|
||||
ReturnURL: getString(configMap, "return_url"),
|
||||
AppPrivateKey: getString(configMap, "app_private_key"),
|
||||
AlipayPublicKey: getString(configMap, "alipay_public_key"),
|
||||
Sandbox: getBool(configMap, "sandbox"),
|
||||
GatewayURL: getString(configMap, "gateway_url"),
|
||||
SupportNative: getBool(configMap, "support_native"),
|
||||
SupportJSAPI: getBool(configMap, "support_jsapi"),
|
||||
SupportAPP: getBool(configMap, "support_app"),
|
||||
SupportH5: getBool(configMap, "support_h5"),
|
||||
}
|
||||
|
||||
return alipayConfig, nil
|
||||
}
|
||||
|
||||
// getString 从map中获取string值
|
||||
func getString(m map[string]interface{}, key string) string {
|
||||
if val, ok := m[key]; ok {
|
||||
if str, ok := val.(string); ok {
|
||||
return str
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getBool 从map中获取bool值
|
||||
func getBool(m map[string]interface{}, key string) bool {
|
||||
if val, ok := m[key]; ok {
|
||||
if b, ok := val.(bool); ok {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// buildConfigMap 将PaymentConfig结构体转换为map
|
||||
func buildConfigMap(config *entity.PaymentConfig) map[string]interface{} {
|
||||
result := map[string]interface{}{
|
||||
"app_id": config.AppID,
|
||||
"mch_id": config.MchID,
|
||||
"api_key": config.APIKey,
|
||||
"notify_url": config.NotifyURL,
|
||||
"return_url": config.ReturnURL,
|
||||
"cert_path": config.CertPath,
|
||||
"key_path": config.KeyPath,
|
||||
"app_private_key": config.AppPrivateKey,
|
||||
"alipay_public_key": config.AlipayPublicKey,
|
||||
"sandbox": config.Sandbox,
|
||||
"gateway_url": config.GatewayURL,
|
||||
"support_native": config.SupportNative,
|
||||
"support_jsapi": config.SupportJSAPI,
|
||||
"support_app": config.SupportAPP,
|
||||
"support_h5": config.SupportH5,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// parseConfigMap 将map转换为PaymentConfig结构体
|
||||
func parseConfigMap(payMethod string, configMap map[string]interface{}) *entity.PaymentConfig {
|
||||
config := &entity.PaymentConfig{
|
||||
PayMethod: payMethod,
|
||||
ConfigName: payMethod + "配置",
|
||||
AppID: getString(configMap, "app_id"),
|
||||
MchID: getString(configMap, "mch_id"),
|
||||
APIKey: getString(configMap, "api_key"),
|
||||
NotifyURL: getString(configMap, "notify_url"),
|
||||
ReturnURL: getString(configMap, "return_url"),
|
||||
CertPath: getString(configMap, "cert_path"),
|
||||
KeyPath: getString(configMap, "key_path"),
|
||||
AppPrivateKey: getString(configMap, "app_private_key"),
|
||||
AlipayPublicKey: getString(configMap, "alipay_public_key"),
|
||||
Sandbox: getBool(configMap, "sandbox"),
|
||||
GatewayURL: getString(configMap, "gateway_url"),
|
||||
SupportNative: getBool(configMap, "support_native"),
|
||||
SupportJSAPI: getBool(configMap, "support_jsapi"),
|
||||
SupportAPP: getBool(configMap, "support_app"),
|
||||
SupportH5: getBool(configMap, "support_h5"),
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// parseConfigMapToEntity 将map中的配置更新到实体中
|
||||
func parseConfigMapToEntity(payMethod string, configMap map[string]interface{}, config *entity.PaymentConfig) {
|
||||
config.AppID = getString(configMap, "app_id")
|
||||
config.MchID = getString(configMap, "mch_id")
|
||||
config.APIKey = getString(configMap, "api_key")
|
||||
config.NotifyURL = getString(configMap, "notify_url")
|
||||
config.ReturnURL = getString(configMap, "return_url")
|
||||
config.CertPath = getString(configMap, "cert_path")
|
||||
config.KeyPath = getString(configMap, "key_path")
|
||||
config.AppPrivateKey = getString(configMap, "app_private_key")
|
||||
config.AlipayPublicKey = getString(configMap, "alipay_public_key")
|
||||
config.Sandbox = getBool(configMap, "sandbox")
|
||||
config.GatewayURL = getString(configMap, "gateway_url")
|
||||
config.SupportNative = getBool(configMap, "support_native")
|
||||
config.SupportJSAPI = getBool(configMap, "support_jsapi")
|
||||
config.SupportAPP = getBool(configMap, "support_app")
|
||||
config.SupportH5 = getBool(configMap, "support_h5")
|
||||
}
|
||||
|
||||
// convertEntityToConfigMap 将实体转换为配置map
|
||||
func convertEntityToConfigMap(config *entity.PaymentConfig) map[string]interface{} {
|
||||
return buildConfigMap(config)
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||
"order/dao"
|
||||
"order/model/entity"
|
||||
)
|
||||
|
||||
var (
|
||||
orderService *OrderService
|
||||
paymentService *PaymentService
|
||||
)
|
||||
|
||||
// InitServices 初始化服务
|
||||
func InitServices() error {
|
||||
ctx := context.Background()
|
||||
|
||||
// 创建订单集合映射(模拟数据)
|
||||
orderCollections := make(map[entity.OrderStatus]*mongo.Collection)
|
||||
|
||||
// 创建DAO实例
|
||||
orderDao := dao.NewOrderDao(orderCollections)
|
||||
paymentConfigDao := dao.NewPaymentConfigDao(nil)
|
||||
paymentRecordDao := dao.NewPaymentRecordDao(nil)
|
||||
refundRecordDao := dao.NewRefundRecordDao(nil)
|
||||
|
||||
// 创建服务实例
|
||||
orderService = NewOrderService(orderDao)
|
||||
paymentService = NewPaymentService(
|
||||
orderDao,
|
||||
paymentConfigDao,
|
||||
paymentRecordDao,
|
||||
refundRecordDao,
|
||||
)
|
||||
|
||||
g.Log().Info(ctx, "服务初始化完成")
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOrderService 获取订单服务实例
|
||||
func GetOrderService() *OrderService {
|
||||
return orderService
|
||||
}
|
||||
|
||||
// GetPaymentService 获取支付服务实例
|
||||
func GetPaymentService() *PaymentService {
|
||||
return paymentService
|
||||
}
|
||||
Reference in New Issue
Block a user