初始化项目
This commit is contained in:
16
consts/collections.go
Normal file
16
consts/collections.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
// 订单集合常量
|
||||||
|
const (
|
||||||
|
OrderPendingCollection = "orders_pending"
|
||||||
|
OrderPaidCollection = "orders_paid"
|
||||||
|
OrderShippedCollection = "orders_shipped"
|
||||||
|
OrderCompletedCollection = "orders_completed"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 支付相关集合常量
|
||||||
|
const (
|
||||||
|
PaymentConfigCollection = "payment_configs"
|
||||||
|
PaymentRecordCollection = "payment_records"
|
||||||
|
RefundRecordCollection = "refund_records"
|
||||||
|
)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package entity
|
package consts
|
||||||
|
|
||||||
// OrderStatus 订单状态枚举
|
// OrderStatus 订单状态枚举
|
||||||
// 用于标识订单当前所处的状态
|
// 用于标识订单当前所处的状态
|
||||||
@@ -2,380 +2,71 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/net/ghttp"
|
|
||||||
"order/model/dto"
|
"order/model/dto"
|
||||||
"order/service"
|
"order/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type order struct{}
|
||||||
|
|
||||||
// Order 订单控制器
|
// Order 订单控制器
|
||||||
|
var Order = new(order)
|
||||||
type Order struct{}
|
|
||||||
|
|
||||||
var OrderController = &Order{}
|
|
||||||
|
|
||||||
// Create 创建订单
|
// Create 创建订单
|
||||||
func (c *Order) Create(r *ghttp.Request) {
|
func (c *order) Create(ctx context.Context, req *dto.CreateOrderReq) (res *dto.CreateOrderResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req dto.CreateOrderReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析请求参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取订单服务实例
|
|
||||||
orderService := service.GetOrderService()
|
|
||||||
if orderService == nil {
|
|
||||||
g.Log().Error(ctx, "订单服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建订单
|
// 创建订单
|
||||||
resp, err := orderService.CreateOrder(ctx, &req)
|
res, err = service.Order.CreateOrder(ctx, req)
|
||||||
if err != nil {
|
return
|
||||||
g.Log().Error(ctx, "创建订单失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": resp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pay 支付订单
|
// Pay 支付订单
|
||||||
func (c *Order) Pay(r *ghttp.Request) {
|
func (c *order) Pay(ctx context.Context, req *dto.PayOrderReq) (res *dto.PayOrderResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req dto.PayOrderReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析请求参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取支付服务实例
|
|
||||||
paymentService := service.GetPaymentService()
|
|
||||||
if paymentService == nil {
|
|
||||||
g.Log().Error(ctx, "支付服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付订单
|
// 支付订单
|
||||||
resp, err := paymentService.PayOrder(ctx, &req)
|
res, err = service.Payment.PayOrder(ctx, req)
|
||||||
if err != nil {
|
return
|
||||||
g.Log().Error(ctx, "支付订单失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": resp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query 查询订单详情
|
// Query 查询订单详情
|
||||||
func (c *Order) Query(r *ghttp.Request) {
|
func (c *order) Query(ctx context.Context, req *dto.QueryOrderReq) (res *dto.QueryOrderResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req dto.QueryOrderReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析请求参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取订单服务实例
|
|
||||||
orderService := service.GetOrderService()
|
|
||||||
if orderService == nil {
|
|
||||||
g.Log().Error(ctx, "订单服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询订单
|
// 查询订单
|
||||||
resp, err := orderService.QueryOrder(ctx, &req)
|
res, err = service.Order.QueryOrder(ctx, req)
|
||||||
if err != nil {
|
return
|
||||||
g.Log().Error(ctx, "查询订单失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": resp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel 取消订单
|
// Cancel 取消订单
|
||||||
func (c *Order) Cancel(r *ghttp.Request) {
|
func (c *order) Cancel(ctx context.Context, req *dto.CancelOrderReq) (res *dto.CancelOrderResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req dto.CancelOrderReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析请求参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取订单服务实例
|
|
||||||
orderService := service.GetOrderService()
|
|
||||||
if orderService == nil {
|
|
||||||
g.Log().Error(ctx, "订单服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取消订单
|
// 取消订单
|
||||||
resp, err := orderService.CancelOrder(ctx, &req)
|
res, err = service.Order.CancelOrder(ctx, req)
|
||||||
if err != nil {
|
return
|
||||||
g.Log().Error(ctx, "取消订单失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": resp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refund 退款
|
// Refund 退款
|
||||||
func (c *Order) Refund(r *ghttp.Request) {
|
func (c *order) Refund(ctx context.Context, req *dto.RefundOrderReq) (res *dto.RefundOrderResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req dto.RefundOrderReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析请求参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取支付服务实例
|
|
||||||
paymentService := service.GetPaymentService()
|
|
||||||
if paymentService == nil {
|
|
||||||
g.Log().Error(ctx, "支付服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退款
|
// 退款
|
||||||
resp, err := paymentService.RefundOrder(ctx, &req)
|
res, err = service.Payment.RefundOrder(ctx, req)
|
||||||
if err != nil {
|
return
|
||||||
g.Log().Error(ctx, "退款失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": resp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List 查询订单列表
|
// List 查询订单列表
|
||||||
func (c *Order) List(r *ghttp.Request) {
|
func (c *order) List(ctx context.Context, req *dto.ListOrdersReq) (res *dto.ListOrdersResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req dto.ListOrdersReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析请求参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取订单服务实例
|
|
||||||
orderService := service.GetOrderService()
|
|
||||||
if orderService == nil {
|
|
||||||
g.Log().Error(ctx, "订单服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询订单列表
|
// 查询订单列表
|
||||||
resp, err := orderService.ListOrders(ctx, &req)
|
res, err = service.Order.ListOrders(ctx, req)
|
||||||
if err != nil {
|
return
|
||||||
g.Log().Error(ctx, "查询订单列表失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": resp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaymentNotify 支付回调
|
// PaymentNotify 支付回调
|
||||||
func (c *Order) PaymentNotify(r *ghttp.Request) {
|
func (c *order) PaymentNotify(ctx context.Context, req *dto.PaymentNotifyReq) (res *dto.PaymentNotifyResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req service.PaymentNotifyReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析支付回调参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取支付服务实例
|
|
||||||
paymentService := service.GetPaymentService()
|
|
||||||
if paymentService == nil {
|
|
||||||
g.Log().Error(ctx, "支付服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理支付回调
|
// 处理支付回调
|
||||||
if err := paymentService.HandlePaymentNotify(ctx, &req); err != nil {
|
err = service.Payment.HandlePaymentNotify(ctx, req)
|
||||||
g.Log().Error(ctx, "处理支付回调失败:", err)
|
return &dto.PaymentNotifyResp{
|
||||||
r.Response.WriteJsonExit(g.Map{
|
Success: err == nil,
|
||||||
"code": 500,
|
}, err
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefundNotify 退款回调
|
// RefundNotify 退款回调
|
||||||
func (c *Order) RefundNotify(r *ghttp.Request) {
|
func (c *order) RefundNotify(ctx context.Context, req *dto.RefundNotifyReq) (res *dto.RefundNotifyResp, err error) {
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
var req service.RefundNotifyReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
g.Log().Error(ctx, "解析退款回调参数失败:", err)
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 400,
|
|
||||||
"message": "参数错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取支付服务实例
|
|
||||||
paymentService := service.GetPaymentService()
|
|
||||||
if paymentService == nil {
|
|
||||||
g.Log().Error(ctx, "支付服务未初始化")
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": "服务内部错误",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理退款回调
|
// 处理退款回调
|
||||||
if err := paymentService.HandleRefundNotify(ctx, &req); err != nil {
|
err = service.Payment.HandleRefundNotify(ctx, req)
|
||||||
g.Log().Error(ctx, "处理退款回调失败:", err)
|
return &dto.RefundNotifyResp{
|
||||||
r.Response.WriteJsonExit(g.Map{
|
Success: err == nil,
|
||||||
"code": 500,
|
}, err
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJson(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/net/ghttp"
|
"github.com/gogf/gf/v2/net/ghttp"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
|
||||||
"order/model/dto"
|
"order/model/dto"
|
||||||
"order/service"
|
"order/service"
|
||||||
)
|
)
|
||||||
@@ -27,45 +26,8 @@ func (c *PaymentConfigController) CreatePaymentConfig(r *ghttp.Request) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// 构建支付配置实体
|
resp, err := service.PaymentConfig.CreatePaymentConfig(ctx, &req)
|
||||||
config := &service.PaymentConfig{
|
if err != nil {
|
||||||
TenantID: req.TenantID,
|
|
||||||
PayMethod: req.PayMethod,
|
|
||||||
ConfigType: req.ConfigType,
|
|
||||||
Environment: req.Environment,
|
|
||||||
IsEnabled: req.IsEnabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.WechatConfig != nil {
|
|
||||||
config.WechatConfig = &service.WechatConfig{
|
|
||||||
AppID: req.WechatConfig.AppID,
|
|
||||||
MchID: req.WechatConfig.MchID,
|
|
||||||
APIKey: req.WechatConfig.APIKey,
|
|
||||||
APIClientCert: req.WechatConfig.APIClientCert,
|
|
||||||
APIClientKey: req.WechatConfig.APIClientKey,
|
|
||||||
NotifyURL: req.WechatConfig.NotifyURL,
|
|
||||||
RefundNotifyURL: req.WechatConfig.RefundNotifyURL,
|
|
||||||
SubAppID: req.WechatConfig.SubAppID,
|
|
||||||
SubMchID: req.WechatConfig.SubMchID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.AlipayConfig != nil {
|
|
||||||
config.AlipayConfig = &service.AlipayConfig{
|
|
||||||
AppID: req.AlipayConfig.AppID,
|
|
||||||
PrivateKey: req.AlipayConfig.PrivateKey,
|
|
||||||
PublicKey: req.AlipayConfig.PublicKey,
|
|
||||||
AlipayPublicKey: req.AlipayConfig.AlipayPublicKey,
|
|
||||||
NotifyURL: req.AlipayConfig.NotifyURL,
|
|
||||||
RefundNotifyURL: req.AlipayConfig.RefundNotifyURL,
|
|
||||||
Format: req.AlipayConfig.Format,
|
|
||||||
Charset: req.AlipayConfig.Charset,
|
|
||||||
SignType: req.AlipayConfig.SignType,
|
|
||||||
IsSandbox: req.AlipayConfig.IsSandbox,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := service.PaymentService.CreatePaymentConfig(ctx, config); err != nil {
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
r.Response.WriteJsonExit(g.Map{
|
||||||
"code": 500,
|
"code": 500,
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
@@ -77,7 +39,7 @@ func (c *PaymentConfigController) CreatePaymentConfig(r *ghttp.Request) {
|
|||||||
r.Response.WriteJsonExit(g.Map{
|
r.Response.WriteJsonExit(g.Map{
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "success",
|
"message": "success",
|
||||||
"data": nil,
|
"data": resp,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,85 +57,103 @@ func (c *PaymentConfigController) UpdatePaymentConfig(r *ghttp.Request) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
update := bson.M{}
|
resp, err := service.PaymentConfig.UpdatePaymentConfig(ctx, &req)
|
||||||
if req.ConfigType != "" {
|
if err != nil {
|
||||||
update["config_type"] = req.ConfigType
|
r.Response.WriteJsonExit(g.Map{
|
||||||
}
|
"code": 500,
|
||||||
if req.Environment != "" {
|
"message": err.Error(),
|
||||||
update["environment"] = req.Environment
|
"data": nil,
|
||||||
}
|
})
|
||||||
if req.IsEnabled != nil {
|
return
|
||||||
update["is_enabled"] = *req.IsEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.WechatConfig != nil {
|
r.Response.WriteJsonExit(g.Map{
|
||||||
wechatConfig := bson.M{}
|
"code": 200,
|
||||||
if req.WechatConfig.AppID != "" {
|
"message": "success",
|
||||||
wechatConfig["app_id"] = req.WechatConfig.AppID
|
"data": resp,
|
||||||
}
|
})
|
||||||
if req.WechatConfig.MchID != "" {
|
}
|
||||||
wechatConfig["mch_id"] = req.WechatConfig.MchID
|
|
||||||
}
|
// GetPaymentConfig 获取支付配置
|
||||||
if req.WechatConfig.APIKey != "" {
|
func (c *PaymentConfigController) GetPaymentConfig(r *ghttp.Request) {
|
||||||
wechatConfig["api_key"] = req.WechatConfig.APIKey
|
var req dto.QueryPaymentConfigReq
|
||||||
}
|
if err := r.Parse(&req); err != nil {
|
||||||
if req.WechatConfig.APIClientCert != "" {
|
r.Response.WriteJsonExit(g.Map{
|
||||||
wechatConfig["api_client_cert"] = req.WechatConfig.APIClientCert
|
"code": 400,
|
||||||
}
|
"message": err.Error(),
|
||||||
if req.WechatConfig.APIClientKey != "" {
|
"data": nil,
|
||||||
wechatConfig["api_client_key"] = req.WechatConfig.APIClientKey
|
})
|
||||||
}
|
return
|
||||||
if req.WechatConfig.NotifyURL != "" {
|
|
||||||
wechatConfig["notify_url"] = req.WechatConfig.NotifyURL
|
|
||||||
}
|
|
||||||
if req.WechatConfig.RefundNotifyURL != "" {
|
|
||||||
wechatConfig["refund_notify_url"] = req.WechatConfig.RefundNotifyURL
|
|
||||||
}
|
|
||||||
if req.WechatConfig.SubAppID != "" {
|
|
||||||
wechatConfig["sub_app_id"] = req.WechatConfig.SubAppID
|
|
||||||
}
|
|
||||||
if req.WechatConfig.SubMchID != "" {
|
|
||||||
wechatConfig["sub_mch_id"] = req.WechatConfig.SubMchID
|
|
||||||
}
|
|
||||||
update["wechat_config"] = wechatConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.AlipayConfig != nil {
|
ctx := context.Background()
|
||||||
alipayConfig := bson.M{}
|
|
||||||
if req.AlipayConfig.AppID != "" {
|
resp, err := service.PaymentConfig.GetPaymentConfig(ctx, &req)
|
||||||
alipayConfig["app_id"] = req.AlipayConfig.AppID
|
if err != nil {
|
||||||
}
|
r.Response.WriteJsonExit(g.Map{
|
||||||
if req.AlipayConfig.PrivateKey != "" {
|
"code": 500,
|
||||||
alipayConfig["private_key"] = req.AlipayConfig.PrivateKey
|
"message": err.Error(),
|
||||||
}
|
"data": nil,
|
||||||
if req.AlipayConfig.PublicKey != "" {
|
})
|
||||||
alipayConfig["public_key"] = req.AlipayConfig.PublicKey
|
return
|
||||||
}
|
|
||||||
if req.AlipayConfig.AlipayPublicKey != "" {
|
|
||||||
alipayConfig["alipay_public_key"] = req.AlipayConfig.AlipayPublicKey
|
|
||||||
}
|
|
||||||
if req.AlipayConfig.NotifyURL != "" {
|
|
||||||
alipayConfig["notify_url"] = req.AlipayConfig.NotifyURL
|
|
||||||
}
|
|
||||||
if req.AlipayConfig.RefundNotifyURL != "" {
|
|
||||||
alipayConfig["refund_notify_url"] = req.AlipayConfig.RefundNotifyURL
|
|
||||||
}
|
|
||||||
if req.AlipayConfig.Format != "" {
|
|
||||||
alipayConfig["format"] = req.AlipayConfig.Format
|
|
||||||
}
|
|
||||||
if req.AlipayConfig.Charset != "" {
|
|
||||||
alipayConfig["charset"] = req.AlipayConfig.Charset
|
|
||||||
}
|
|
||||||
if req.AlipayConfig.SignType != "" {
|
|
||||||
alipayConfig["sign_type"] = req.AlipayConfig.SignType
|
|
||||||
}
|
|
||||||
if req.AlipayConfig.IsSandbox != false {
|
|
||||||
alipayConfig["is_sandbox"] = req.AlipayConfig.IsSandbox
|
|
||||||
}
|
|
||||||
update["alipay_config"] = alipayConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := service.PaymentService.UpdatePaymentConfig(ctx, req.ID, update); err != nil {
|
r.Response.WriteJsonExit(g.Map{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": resp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPaymentConfigList 获取支付配置列表
|
||||||
|
func (c *PaymentConfigController) GetPaymentConfigList(r *ghttp.Request) {
|
||||||
|
tenantID := r.Get("tenant_id").String()
|
||||||
|
if tenantID == "" {
|
||||||
|
r.Response.WriteJsonExit(g.Map{
|
||||||
|
"code": 400,
|
||||||
|
"message": "租户ID不能为空",
|
||||||
|
"data": nil,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
resp, err := service.PaymentConfig.GetPaymentConfigList(ctx, tenantID)
|
||||||
|
if err != nil {
|
||||||
|
r.Response.WriteJsonExit(g.Map{
|
||||||
|
"code": 500,
|
||||||
|
"message": err.Error(),
|
||||||
|
"data": nil,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Response.WriteJsonExit(g.Map{
|
||||||
|
"code": 200,
|
||||||
|
"message": "success",
|
||||||
|
"data": resp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePaymentConfig 删除支付配置
|
||||||
|
func (c *PaymentConfigController) DeletePaymentConfig(r *ghttp.Request) {
|
||||||
|
tenantID := r.Get("tenant_id").String()
|
||||||
|
configID := r.Get("config_id").String()
|
||||||
|
|
||||||
|
if tenantID == "" || configID == "" {
|
||||||
|
r.Response.WriteJsonExit(g.Map{
|
||||||
|
"code": 400,
|
||||||
|
"message": "租户ID和配置ID不能为空",
|
||||||
|
"data": nil,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
err := service.PaymentConfig.DeletePaymentConfig(ctx, tenantID, configID)
|
||||||
|
if err != nil {
|
||||||
r.Response.WriteJsonExit(g.Map{
|
r.Response.WriteJsonExit(g.Map{
|
||||||
"code": 500,
|
"code": 500,
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
@@ -189,39 +169,15 @@ func (c *PaymentConfigController) UpdatePaymentConfig(r *ghttp.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryPaymentConfig 查询支付配置
|
// EnablePaymentConfig 启用支付配置
|
||||||
func (c *PaymentConfigController) QueryPaymentConfig(r *ghttp.Request) {
|
func (c *PaymentConfigController) EnablePaymentConfig(r *ghttp.Request) {
|
||||||
tentID := r.Get("tenant_id").String()
|
tenantID := r.Get("tenant_id").String()
|
||||||
payMethod := r.Get("pay_method").String()
|
configID := r.Get("config_id").String()
|
||||||
configType := r.Get("config_type").String()
|
|
||||||
environment := r.Get("environment").String()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
if tenantID == "" || configID == "" {
|
||||||
|
|
||||||
config, err := service.PaymentService.QueryPaymentConfig(ctx, tentID, payMethod, configType, environment)
|
|
||||||
if err != nil {
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
"data": nil,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": config,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListPaymentConfigs 查询支付配置列表
|
|
||||||
func (c *PaymentConfigController) ListPaymentConfigs(r *ghttp.Request) {
|
|
||||||
var req dto.QueryPaymentConfigReq
|
|
||||||
if err := r.Parse(&req); err != nil {
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
r.Response.WriteJsonExit(g.Map{
|
||||||
"code": 400,
|
"code": 400,
|
||||||
"message": err.Error(),
|
"message": "租户ID和配置ID不能为空",
|
||||||
"data": nil,
|
"data": nil,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -229,28 +185,7 @@ func (c *PaymentConfigController) ListPaymentConfigs(r *ghttp.Request) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
filter := bson.M{"tenant_id": req.TenantID}
|
err := service.PaymentConfig.EnablePaymentConfig(ctx, tenantID, configID)
|
||||||
if req.PayMethod != "" {
|
|
||||||
filter["pay_method"] = req.PayMethod
|
|
||||||
}
|
|
||||||
if req.ConfigType != "" {
|
|
||||||
filter["config_type"] = req.ConfigType
|
|
||||||
}
|
|
||||||
if req.Environment != "" {
|
|
||||||
filter["environment"] = req.Environment
|
|
||||||
}
|
|
||||||
if req.IsEnabled != nil {
|
|
||||||
filter["is_enabled"] = *req.IsEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Page <= 0 {
|
|
||||||
req.Page = 1
|
|
||||||
}
|
|
||||||
if req.PageSize <= 0 {
|
|
||||||
req.PageSize = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
configs, total, err := service.PaymentService.ListPaymentConfigs(ctx, filter, req.Page, req.PageSize)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Response.WriteJsonExit(g.Map{
|
r.Response.WriteJsonExit(g.Map{
|
||||||
"code": 500,
|
"code": 500,
|
||||||
@@ -260,57 +195,42 @@ func (c *PaymentConfigController) ListPaymentConfigs(r *ghttp.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := dto.PaymentConfigListResp{
|
r.Response.WriteJsonExit(g.Map{
|
||||||
List: make([]dto.PaymentConfigResp, 0, len(configs)),
|
"code": 200,
|
||||||
Total: total,
|
"message": "success",
|
||||||
Page: req.Page,
|
"data": nil,
|
||||||
PageSize: req.PageSize,
|
})
|
||||||
TotalPage: int((total + int64(req.PageSize) - 1) / int64(req.PageSize)),
|
}
|
||||||
|
|
||||||
|
// DisablePaymentConfig 禁用支付配置
|
||||||
|
func (c *PaymentConfigController) DisablePaymentConfig(r *ghttp.Request) {
|
||||||
|
tenantID := r.Get("tenant_id").String()
|
||||||
|
configID := r.Get("config_id").String()
|
||||||
|
|
||||||
|
if tenantID == "" || configID == "" {
|
||||||
|
r.Response.WriteJsonExit(g.Map{
|
||||||
|
"code": 400,
|
||||||
|
"message": "租户ID和配置ID不能为空",
|
||||||
|
"data": nil,
|
||||||
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, config := range configs {
|
ctx := context.Background()
|
||||||
configResp := dto.PaymentConfigResp{
|
|
||||||
ID: config.ID.Hex(),
|
|
||||||
TenantID: config.TenantID,
|
|
||||||
PayMethod: config.PayMethod,
|
|
||||||
ConfigType: config.ConfigType,
|
|
||||||
Environment: config.Environment,
|
|
||||||
IsEnabled: config.IsEnabled,
|
|
||||||
CreatedAt: config.CreatedAt,
|
|
||||||
UpdatedAt: config.UpdatedAt,
|
|
||||||
CreatedBy: config.CreatedBy,
|
|
||||||
UpdatedBy: config.UpdatedBy,
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.WechatConfig != nil {
|
err := service.PaymentConfig.DisablePaymentConfig(ctx, tenantID, configID)
|
||||||
configResp.WechatConfig = &dto.WechatConfigResp{
|
if err != nil {
|
||||||
AppID: config.WechatConfig.AppID,
|
r.Response.WriteJsonExit(g.Map{
|
||||||
MchID: config.WechatConfig.MchID,
|
"code": 500,
|
||||||
NotifyURL: config.WechatConfig.NotifyURL,
|
"message": err.Error(),
|
||||||
RefundNotifyURL: config.WechatConfig.RefundNotifyURL,
|
"data": nil,
|
||||||
SubAppID: config.WechatConfig.SubAppID,
|
})
|
||||||
SubMchID: config.WechatConfig.SubMchID,
|
return
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.AlipayConfig != nil {
|
|
||||||
configResp.AlipayConfig = &dto.AlipayConfigResp{
|
|
||||||
AppID: config.AlipayConfig.AppID,
|
|
||||||
NotifyURL: config.AlipayConfig.NotifyURL,
|
|
||||||
RefundNotifyURL: config.AlipayConfig.RefundNotifyURL,
|
|
||||||
Format: config.AlipayConfig.Format,
|
|
||||||
Charset: config.AlipayConfig.Charset,
|
|
||||||
SignType: config.AlipayConfig.SignType,
|
|
||||||
IsSandbox: config.AlipayConfig.IsSandbox,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.List = append(resp.List, configResp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Response.WriteJsonExit(g.Map{
|
r.Response.WriteJsonExit(g.Map{
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "success",
|
"message": "success",
|
||||||
"data": resp,
|
"data": nil,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
150
dao/order_dao.go
150
dao/order_dao.go
@@ -6,59 +6,56 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"gitee.com/red-future---jilin-g/common/mongo"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"order/consts"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
|
||||||
"order/model/entity"
|
"order/model/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OrderDao 订单数据访问对象
|
type order struct{}
|
||||||
// 支持按状态拆分的订单表操作
|
|
||||||
|
|
||||||
type OrderDao struct {
|
// Order 订单数据访问对象
|
||||||
collections map[entity.OrderStatus]*mongo.Collection
|
var Order = &order{}
|
||||||
}
|
|
||||||
|
|
||||||
// NewOrderDao 创建订单DAO实例
|
|
||||||
func NewOrderDao(collections map[entity.OrderStatus]*mongo.Collection) *OrderDao {
|
|
||||||
return &OrderDao{
|
|
||||||
collections: collections,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getCollection 根据订单状态获取对应的集合
|
// getCollection 根据订单状态获取对应的集合
|
||||||
func (d *OrderDao) getCollection(status entity.OrderStatus) (*mongo.Collection, error) {
|
func (d *order) getCollection(status consts.OrderStatus) (string, error) {
|
||||||
collection, exists := d.collections[status]
|
switch status {
|
||||||
if !exists {
|
case consts.OrderStatusPending:
|
||||||
return nil, fmt.Errorf("collection for status %s not found", status)
|
return consts.OrderPendingCollection, nil
|
||||||
|
case consts.OrderStatusPaid:
|
||||||
|
return consts.OrderPaidCollection, nil
|
||||||
|
case consts.OrderStatusShipped:
|
||||||
|
return consts.OrderShippedCollection, nil
|
||||||
|
case consts.OrderStatusCompleted:
|
||||||
|
return consts.OrderCompletedCollection, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("collection for status %s not found", status)
|
||||||
}
|
}
|
||||||
return collection, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatePendingOrder 创建待支付订单
|
// CreatePendingOrder 创建待支付订单
|
||||||
func (d *OrderDao) CreatePendingOrder(ctx context.Context, order *entity.OrderPending) error {
|
func (d *order) CreatePendingOrder(ctx context.Context, order *entity.OrderPending) error {
|
||||||
collection, err := d.getCollection(entity.OrderStatusPending)
|
collection, err := d.getCollection(consts.OrderStatusPending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
order.ID = primitive.NewObjectID()
|
order.ID = bson.NewObjectID()
|
||||||
order.CreatedAt = time.Now()
|
order.CreatedAt = time.Now()
|
||||||
order.UpdatedAt = time.Now()
|
order.UpdatedAt = time.Now()
|
||||||
|
|
||||||
_, err = collection.InsertOne(ctx, order)
|
_, err = mongo.Insert(ctx, []interface{}{order}, collection)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrderByNo 根据订单号查询订单(自动识别状态)
|
// GetOrderByNo 根据订单号查询订单(自动识别状态)
|
||||||
func (d *OrderDao) GetOrderByNo(ctx context.Context, tenantID, orderNo string) (interface{}, entity.OrderStatus, error) {
|
func (d *order) GetOrderByNo(ctx context.Context, tenantID, orderNo string) (interface{}, consts.OrderStatus, error) {
|
||||||
// 按状态优先级搜索(从最新状态开始)
|
// 按状态优先级搜索(从最新状态开始)
|
||||||
statuses := []entity.OrderStatus{
|
statuses := []consts.OrderStatus{
|
||||||
entity.OrderStatusCompleted,
|
consts.OrderStatusCompleted,
|
||||||
entity.OrderStatusShipped,
|
consts.OrderStatusShipped,
|
||||||
entity.OrderStatusPaid,
|
consts.OrderStatusPaid,
|
||||||
entity.OrderStatusPending,
|
consts.OrderStatusPending,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
@@ -68,22 +65,22 @@ func (d *OrderDao) GetOrderByNo(ctx context.Context, tenantID, orderNo string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch status {
|
switch status {
|
||||||
case entity.OrderStatusPending:
|
case consts.OrderStatusPending:
|
||||||
var order entity.OrderPending
|
var order entity.OrderPending
|
||||||
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
||||||
return &order, status, nil
|
return &order, status, nil
|
||||||
}
|
}
|
||||||
case entity.OrderStatusPaid:
|
case consts.OrderStatusPaid:
|
||||||
var order entity.OrderPaid
|
var order entity.OrderPaid
|
||||||
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
||||||
return &order, status, nil
|
return &order, status, nil
|
||||||
}
|
}
|
||||||
case entity.OrderStatusShipped:
|
case consts.OrderStatusShipped:
|
||||||
var order entity.OrderShipped
|
var order entity.OrderShipped
|
||||||
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
||||||
return &order, status, nil
|
return &order, status, nil
|
||||||
}
|
}
|
||||||
case entity.OrderStatusCompleted:
|
case consts.OrderStatusCompleted:
|
||||||
var order entity.OrderCompleted
|
var order entity.OrderCompleted
|
||||||
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
|
||||||
return &order, status, nil
|
return &order, status, nil
|
||||||
@@ -95,21 +92,21 @@ func (d *OrderDao) GetOrderByNo(ctx context.Context, tenantID, orderNo string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// findOrderByNo 通用订单查询方法
|
// findOrderByNo 通用订单查询方法
|
||||||
func (d *OrderDao) findOrderByNo(collection *mongo.Collection, ctx context.Context, tenantID, orderNo string, result interface{}) error {
|
func (d *order) findOrderByNo(collection string, ctx context.Context, tenantID, orderNo string, result interface{}) error {
|
||||||
filter := bson.M{
|
filter := bson.M{
|
||||||
"tenant_id": tenantID,
|
"tenant_id": tenantID,
|
||||||
"order_no": orderNo,
|
"order_no": orderNo,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := collection.FindOne(ctx, filter).Decode(result)
|
err := mongo.FindOne(ctx, filter, result, collection)
|
||||||
if err == mongo.ErrNoDocuments {
|
if err != nil {
|
||||||
return errors.New("order not found")
|
return errors.New("order not found")
|
||||||
}
|
}
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveOrderToStatus 将订单从一个状态移动到另一个状态
|
// MoveOrderToStatus 将订单从一个状态移动到另一个状态
|
||||||
func (d *OrderDao) MoveOrderToStatus(ctx context.Context, fromStatus, toStatus entity.OrderStatus, tenantID, orderNo string, updateData bson.M) error {
|
func (d *order) MoveOrderToStatus(ctx context.Context, fromStatus, toStatus consts.OrderStatus, tenantID, orderNo string, updateData bson.M) error {
|
||||||
// 获取源集合
|
// 获取源集合
|
||||||
srcCollection, err := d.getCollection(fromStatus)
|
srcCollection, err := d.getCollection(fromStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -129,7 +126,7 @@ func (d *OrderDao) MoveOrderToStatus(ctx context.Context, fromStatus, toStatus e
|
|||||||
"order_no": orderNo,
|
"order_no": orderNo,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = srcCollection.FindOne(ctx, filter).Decode(&orderData)
|
err = mongo.FindOne(ctx, filter, &orderData, srcCollection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -141,35 +138,36 @@ func (d *OrderDao) MoveOrderToStatus(ctx context.Context, fromStatus, toStatus e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 插入到目标集合
|
// 插入到目标集合
|
||||||
_, err = destCollection.InsertOne(ctx, orderData)
|
_, err = mongo.Insert(ctx, []interface{}{orderData}, destCollection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从源集合删除
|
// 从源集合删除
|
||||||
_, err = srcCollection.DeleteOne(ctx, filter)
|
_, err = mongo.Delete(ctx, filter, srcCollection)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePendingOrder 更新待支付订单
|
// UpdatePendingOrder 更新待支付订单
|
||||||
func (d *OrderDao) UpdatePendingOrder(ctx context.Context, tenantID, orderNo string, update bson.M) error {
|
func (d *order) UpdatePendingOrder(ctx context.Context, tenantID, orderNo string, update bson.M) error {
|
||||||
collection, err := d.getCollection(entity.OrderStatusPending)
|
collection, err := d.getCollection(consts.OrderStatusPending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
update["updated_at"] = time.Now()
|
update["updated_at"] = time.Now()
|
||||||
|
|
||||||
_, err = collection.UpdateOne(ctx, bson.M{
|
filter := bson.M{
|
||||||
"tenant_id": tenantID,
|
"tenant_id": tenantID,
|
||||||
"order_no": orderNo,
|
"order_no": orderNo,
|
||||||
}, bson.M{"$set": update})
|
}
|
||||||
|
_, err = mongo.Update(ctx, filter, bson.M{"$set": update}, collection)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListOrdersByStatus 根据状态查询订单列表
|
// ListOrdersByStatus 根据状态查询订单列表
|
||||||
func (d *OrderDao) ListOrdersByStatus(ctx context.Context, status entity.OrderStatus, tenantID, userID string, page, pageSize int) (interface{}, int64, error) {
|
func (d *order) ListOrdersByStatus(ctx context.Context, status consts.OrderStatus, tenantID, userID string, page, pageSize int) (interface{}, int64, error) {
|
||||||
collection, err := d.getCollection(status)
|
collection, err := d.getCollection(status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -182,47 +180,37 @@ func (d *OrderDao) ListOrdersByStatus(ctx context.Context, status entity.OrderSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 计算总数
|
// 计算总数
|
||||||
total, err := collection.CountDocuments(ctx, filter)
|
total, err := mongo.Count(ctx, filter, collection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页查询
|
// 分页查询(暂时忽略排序和分页,因为 mongo.Find 不支持这些参数)
|
||||||
skip := int64((page - 1) * pageSize)
|
// TODO: 需要在 common/mongo 中添加支持排序和分页的 Find 方法
|
||||||
opt := options.Find().
|
|
||||||
SetSort(bson.D{{Key: "created_at", Value: -1}}).
|
|
||||||
SetSkip(skip).
|
|
||||||
SetLimit(int64(pageSize))
|
|
||||||
|
|
||||||
cursor, err := collection.Find(ctx, filter, opt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
defer cursor.Close(ctx)
|
|
||||||
|
|
||||||
// 根据状态返回对应的订单类型
|
// 根据状态返回对应的订单类型
|
||||||
switch status {
|
switch status {
|
||||||
case entity.OrderStatusPending:
|
case consts.OrderStatusPending:
|
||||||
var orders []entity.OrderPending
|
var orders []entity.OrderPending
|
||||||
if err := cursor.All(ctx, &orders); err != nil {
|
if err := mongo.Find(ctx, filter, &orders, collection); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
return orders, total, nil
|
return orders, total, nil
|
||||||
case entity.OrderStatusPaid:
|
case consts.OrderStatusPaid:
|
||||||
var orders []entity.OrderPaid
|
var orders []entity.OrderPaid
|
||||||
if err := cursor.All(ctx, &orders); err != nil {
|
if err := mongo.Find(ctx, filter, &orders, collection); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
return orders, total, nil
|
return orders, total, nil
|
||||||
case entity.OrderStatusShipped:
|
case consts.OrderStatusShipped:
|
||||||
var orders []entity.OrderShipped
|
var orders []entity.OrderShipped
|
||||||
if err := cursor.All(ctx, &orders); err != nil {
|
if err := mongo.Find(ctx, filter, &orders, collection); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
return orders, total, nil
|
return orders, total, nil
|
||||||
case entity.OrderStatusCompleted:
|
case consts.OrderStatusCompleted:
|
||||||
var orders []entity.OrderCompleted
|
var orders []entity.OrderCompleted
|
||||||
if err := cursor.All(ctx, &orders); err != nil {
|
if err := mongo.Find(ctx, filter, &orders, collection); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
return orders, total, nil
|
return orders, total, nil
|
||||||
@@ -232,8 +220,8 @@ func (d *OrderDao) ListOrdersByStatus(ctx context.Context, status entity.OrderSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetExpiredPendingOrders 获取过期的待支付订单
|
// GetExpiredPendingOrders 获取过期的待支付订单
|
||||||
func (d *OrderDao) GetExpiredPendingOrders(ctx context.Context, tenantID string) ([]entity.OrderPending, error) {
|
func (d *order) GetExpiredPendingOrders(ctx context.Context, tenantID string) ([]entity.OrderPending, error) {
|
||||||
collection, err := d.getCollection(entity.OrderStatusPending)
|
collection, err := d.getCollection(consts.OrderStatusPending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -243,14 +231,8 @@ func (d *OrderDao) GetExpiredPendingOrders(ctx context.Context, tenantID string)
|
|||||||
"expired_at": bson.M{"$lte": time.Now()},
|
"expired_at": bson.M{"$lte": time.Now()},
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor, err := collection.Find(ctx, filter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer cursor.Close(ctx)
|
|
||||||
|
|
||||||
var orders []entity.OrderPending
|
var orders []entity.OrderPending
|
||||||
if err := cursor.All(ctx, &orders); err != nil {
|
if err := mongo.Find(ctx, filter, &orders, collection); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,19 +240,21 @@ func (d *OrderDao) GetExpiredPendingOrders(ctx context.Context, tenantID string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePayInfo 更新支付信息(待支付订单)
|
// UpdatePayInfo 更新支付信息(待支付订单)
|
||||||
func (d *OrderDao) UpdatePayInfo(ctx context.Context, tenantID, orderNo string, payInfo entity.PayInfo) error {
|
func (d *order) UpdatePayInfo(ctx context.Context, tenantID, orderNo string, payInfo entity.PayInfo) error {
|
||||||
collection, err := d.getCollection(entity.OrderStatusPending)
|
collection, err := d.getCollection(consts.OrderStatusPending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = collection.UpdateOne(ctx, bson.M{
|
filter := bson.M{
|
||||||
"tenant_id": tenantID,
|
"tenant_id": tenantID,
|
||||||
"order_no": orderNo,
|
"order_no": orderNo,
|
||||||
}, bson.M{"$set": bson.M{
|
}
|
||||||
|
update := bson.M{
|
||||||
"pay_info": payInfo,
|
"pay_info": payInfo,
|
||||||
"updated_at": time.Now(),
|
"updated_at": time.Now(),
|
||||||
}})
|
}
|
||||||
|
_, err = mongo.Update(ctx, filter, bson.M{"$set": update}, collection)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,228 +2,202 @@ package dao
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"gitee.com/red-future---jilin-g/common/mongo"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"order/consts"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
|
||||||
"order/model/entity"
|
"order/model/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PaymentConfigDao 支付配置数据访问对象
|
type paymentConfig struct{}
|
||||||
|
|
||||||
type PaymentConfigDao struct {
|
// PaymentConfig 支付配置数据访问对象
|
||||||
collection *mongo.Collection
|
var PaymentConfig = new(paymentConfig)
|
||||||
}
|
|
||||||
|
|
||||||
// NewPaymentConfigDao 创建支付配置DAO实例
|
|
||||||
func NewPaymentConfigDao(collection *mongo.Collection) *PaymentConfigDao {
|
|
||||||
return &PaymentConfigDao{
|
|
||||||
collection: collection,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 创建支付配置
|
// Create 创建支付配置
|
||||||
func (d *PaymentConfigDao) Create(ctx context.Context, config *entity.PaymentConfig) error {
|
func (d *paymentConfig) Create(ctx context.Context, config *entity.PaymentConfig) error {
|
||||||
if d.collection == nil {
|
_, err := mongo.Insert(ctx, []interface{}{config}, consts.PaymentConfigCollection)
|
||||||
return errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
config.ID = primitive.NewObjectID()
|
|
||||||
|
|
||||||
_, err := d.collection.InsertOne(ctx, config)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByTenantAndMethod 根据租户和支付方式获取配置
|
// GetByTenantAndMethod 根据租户和支付方式获取配置
|
||||||
func (d *PaymentConfigDao) GetByTenantAndMethod(ctx context.Context, tenantID, payMethod string) (*entity.PaymentConfig, error) {
|
func (d *paymentConfig) GetByTenantAndMethod(ctx context.Context, tenantID, payMethod string) (*entity.PaymentConfig, error) {
|
||||||
if d.collection == nil {
|
|
||||||
return nil, errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
var config entity.PaymentConfig
|
var config entity.PaymentConfig
|
||||||
err := d.collection.FindOne(ctx, bson.M{
|
|
||||||
|
filter := bson.M{
|
||||||
"tenant_id": tenantID,
|
"tenant_id": tenantID,
|
||||||
"pay_method": payMethod,
|
"pay_method": payMethod,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
}).Decode(&config)
|
}
|
||||||
|
|
||||||
if err == mongo.ErrNoDocuments {
|
err := mongo.FindOne(ctx, filter, &config, consts.PaymentConfigCollection)
|
||||||
|
if err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &config, err
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update 更新支付配置
|
// Update 更新支付配置
|
||||||
func (d *PaymentConfigDao) Update(ctx context.Context, id string, update bson.M) error {
|
func (d *paymentConfig) Update(ctx context.Context, config *entity.PaymentConfig) error {
|
||||||
if d.collection == nil {
|
filter := bson.M{"_id": config.ID}
|
||||||
return errors.New("collection not initialized")
|
update := bson.M{
|
||||||
|
"$set": bson.M{
|
||||||
|
"tenant_id": config.TenantID,
|
||||||
|
"pay_method": config.PayMethod,
|
||||||
|
"config_name": config.ConfigName,
|
||||||
|
"description": config.Description,
|
||||||
|
"enabled": config.Enabled,
|
||||||
|
"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,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
objectID, err := primitive.ObjectIDFromHex(id)
|
_, err := mongo.Update(ctx, filter, update, consts.PaymentConfigCollection)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = d.collection.UpdateOne(ctx, bson.M{"_id": objectID}, bson.M{"$set": update})
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListByTenant 查询租户的支付配置列表
|
// GetByID 根据ID获取配置
|
||||||
func (d *PaymentConfigDao) ListByTenant(ctx context.Context, tenantID string) ([]entity.PaymentConfig, error) {
|
func (d *paymentConfig) GetByID(ctx context.Context, id bson.ObjectID) (*entity.PaymentConfig, error) {
|
||||||
if d.collection == nil {
|
var config entity.PaymentConfig
|
||||||
return nil, errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := bson.M{"tenant_id": tenantID}
|
filter := bson.M{"_id": id}
|
||||||
cursor, err := d.collection.Find(ctx, filter)
|
err := mongo.FindOne(ctx, filter, &config, consts.PaymentConfigCollection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer cursor.Close(ctx)
|
|
||||||
|
|
||||||
|
return &config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByTenantID 根据租户ID获取配置列表
|
||||||
|
func (d *paymentConfig) GetByTenantID(ctx context.Context, tenantID string) ([]entity.PaymentConfig, error) {
|
||||||
var configs []entity.PaymentConfig
|
var configs []entity.PaymentConfig
|
||||||
if err := cursor.All(ctx, &configs); err != nil {
|
|
||||||
|
filter := bson.M{"tenant_id": tenantID}
|
||||||
|
err := mongo.Find(ctx, filter, &configs, consts.PaymentConfigCollection)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return configs, nil
|
return configs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaymentRecordDao 支付记录数据访问对象
|
// Delete 删除支付配置
|
||||||
|
func (d *paymentConfig) Delete(ctx context.Context, id bson.ObjectID) error {
|
||||||
|
filter := bson.M{"_id": id}
|
||||||
|
|
||||||
type PaymentRecordDao struct {
|
_, err := mongo.Delete(ctx, filter, consts.PaymentConfigCollection)
|
||||||
collection *mongo.Collection
|
return err
|
||||||
|
}
|
||||||
|
func (d *paymentConfig) ListByTenant(ctx context.Context, tenantID string) ([]entity.PaymentConfig, error) {
|
||||||
|
var configs []entity.PaymentConfig
|
||||||
|
|
||||||
|
filter := bson.M{"tenant_id": tenantID}
|
||||||
|
|
||||||
|
err := mongo.Find(ctx, filter, &configs, consts.PaymentConfigCollection)
|
||||||
|
return configs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPaymentRecordDao 创建支付记录DAO实例
|
type paymentRecord struct{}
|
||||||
func NewPaymentRecordDao(collection *mongo.Collection) *PaymentRecordDao {
|
|
||||||
return &PaymentRecordDao{
|
// PaymentRecord 支付记录数据访问对象
|
||||||
collection: collection,
|
var PaymentRecord = new(paymentRecord)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 创建支付记录
|
// Create 创建支付记录
|
||||||
func (d *PaymentRecordDao) Create(ctx context.Context, record *entity.PaymentRecord) error {
|
func (d *paymentRecord) Create(ctx context.Context, record *entity.PaymentRecord) error {
|
||||||
if d.collection == nil {
|
|
||||||
return errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
record.ID = primitive.NewObjectID()
|
|
||||||
record.CreatedAt = time.Now().Unix()
|
record.CreatedAt = time.Now().Unix()
|
||||||
record.UpdatedAt = time.Now().Unix()
|
record.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
_, err := d.collection.InsertOne(ctx, record)
|
_, err := mongo.Insert(ctx, []interface{}{record}, consts.PaymentRecordCollection)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByOrderNo 根据订单号获取支付记录
|
// GetByOrderNo 根据订单号获取支付记录
|
||||||
func (d *PaymentRecordDao) GetByOrderNo(ctx context.Context, tenantID, orderNo string) (*entity.PaymentRecord, error) {
|
func (d *paymentRecord) GetByOrderNo(ctx context.Context, tenantID, orderNo string) (*entity.PaymentRecord, error) {
|
||||||
if d.collection == nil {
|
|
||||||
return nil, errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
var record entity.PaymentRecord
|
var record entity.PaymentRecord
|
||||||
err := d.collection.FindOne(ctx, bson.M{
|
|
||||||
|
filter := bson.M{
|
||||||
"tenant_id": tenantID,
|
"tenant_id": tenantID,
|
||||||
"order_no": orderNo,
|
"order_no": orderNo,
|
||||||
}).Decode(&record)
|
}
|
||||||
|
|
||||||
if err == mongo.ErrNoDocuments {
|
err := mongo.FindOne(ctx, filter, &record, consts.PaymentRecordCollection)
|
||||||
|
if err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &record, err
|
return &record, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStatus 更新支付记录状态
|
// UpdateStatus 更新支付记录状态
|
||||||
func (d *PaymentRecordDao) UpdateStatus(ctx context.Context, id string, status, transactionID, tradeNo string) error {
|
func (d *paymentRecord) UpdateStatus(ctx context.Context, id string, status, transactionID, tradeNo string) error {
|
||||||
if d.collection == nil {
|
filter := bson.M{"_id": id}
|
||||||
return errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
objectID, err := primitive.ObjectIDFromHex(id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
update := bson.M{
|
update := bson.M{
|
||||||
"status": status,
|
"status": status,
|
||||||
"transaction_id": transactionID,
|
"transaction_id": transactionID,
|
||||||
"trade_no": tradeNo,
|
"trade_no": tradeNo,
|
||||||
"updated_at": time.Now().Unix(),
|
"updated_at": time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = d.collection.UpdateOne(ctx, bson.M{"_id": objectID}, bson.M{"$set": update})
|
_, err := mongo.Update(ctx, filter, bson.M{"$set": update}, consts.PaymentRecordCollection)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefundRecordDao 退款记录数据访问对象
|
type refundRecord struct{}
|
||||||
|
|
||||||
type RefundRecordDao struct {
|
// RefundRecord 退款记录数据访问对象
|
||||||
collection *mongo.Collection
|
var RefundRecord = new(refundRecord)
|
||||||
}
|
|
||||||
|
|
||||||
// NewRefundRecordDao 创建退款记录DAO实例
|
|
||||||
func NewRefundRecordDao(collection *mongo.Collection) *RefundRecordDao {
|
|
||||||
return &RefundRecordDao{
|
|
||||||
collection: collection,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 创建退款记录
|
// Create 创建退款记录
|
||||||
func (d *RefundRecordDao) Create(ctx context.Context, record *entity.RefundRecord) error {
|
func (d *refundRecord) Create(ctx context.Context, record *entity.RefundRecord) error {
|
||||||
if d.collection == nil {
|
|
||||||
return errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
record.ID = primitive.NewObjectID()
|
|
||||||
record.CreatedAt = time.Now().Unix()
|
record.CreatedAt = time.Now().Unix()
|
||||||
record.UpdatedAt = time.Now().Unix()
|
record.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
_, err := d.collection.InsertOne(ctx, record)
|
_, err := mongo.Insert(ctx, []interface{}{record}, consts.RefundRecordCollection)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByRefundNo 根据退款单号获取退款记录
|
// GetByRefundNo 根据退款单号获取退款记录
|
||||||
func (d *RefundRecordDao) GetByRefundNo(ctx context.Context, tenantID, refundNo string) (*entity.RefundRecord, error) {
|
func (d *refundRecord) GetByRefundNo(ctx context.Context, tenantID, refundNo string) (*entity.RefundRecord, error) {
|
||||||
if d.collection == nil {
|
|
||||||
return nil, errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
var record entity.RefundRecord
|
var record entity.RefundRecord
|
||||||
err := d.collection.FindOne(ctx, bson.M{
|
|
||||||
|
filter := bson.M{
|
||||||
"tenant_id": tenantID,
|
"tenant_id": tenantID,
|
||||||
"refund_no": refundNo,
|
"refund_no": refundNo,
|
||||||
}).Decode(&record)
|
}
|
||||||
|
|
||||||
if err == mongo.ErrNoDocuments {
|
err := mongo.FindOne(ctx, filter, &record, consts.RefundRecordCollection)
|
||||||
|
if err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &record, err
|
return &record, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateRefundStatus 更新退款记录状态
|
// UpdateRefundStatus 更新退款记录状态
|
||||||
func (d *RefundRecordDao) UpdateRefundStatus(ctx context.Context, id, status, refundID string) error {
|
func (d *refundRecord) UpdateRefundStatus(ctx context.Context, id, status, refundID string) error {
|
||||||
if d.collection == nil {
|
filter := bson.M{"_id": id}
|
||||||
return errors.New("collection not initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
objectID, err := primitive.ObjectIDFromHex(id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
update := bson.M{
|
update := bson.M{
|
||||||
"status": status,
|
"status": status,
|
||||||
"refund_id": refundID,
|
"refund_id": refundID,
|
||||||
"updated_at": time.Now().Unix(),
|
"updated_at": time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = d.collection.UpdateOne(ctx, bson.M{"_id": objectID}, bson.M{"$set": update})
|
_, err := mongo.Update(ctx, filter, bson.M{"$set": update}, consts.RefundRecordCollection)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
3
go.mod
3
go.mod
@@ -8,7 +8,6 @@ require (
|
|||||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.6
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.6
|
||||||
github.com/gogf/gf/v2 v2.9.6
|
github.com/gogf/gf/v2 v2.9.6
|
||||||
go.mongodb.org/mongo-driver v1.17.6
|
go.mongodb.org/mongo-driver v1.17.6
|
||||||
go.mongodb.org/mongo-driver/v2 v2.4.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -56,7 +55,6 @@ require (
|
|||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
|
||||||
github.com/olekukonko/errors v1.1.0 // indirect
|
github.com/olekukonko/errors v1.1.0 // indirect
|
||||||
github.com/olekukonko/ll v0.0.9 // indirect
|
github.com/olekukonko/ll v0.0.9 // indirect
|
||||||
github.com/olekukonko/tablewriter v1.1.0 // indirect
|
github.com/olekukonko/tablewriter v1.1.0 // indirect
|
||||||
@@ -68,6 +66,7 @@ require (
|
|||||||
github.com/xdg-go/scram v1.1.2 // indirect
|
github.com/xdg-go/scram v1.1.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.4.1 // indirect
|
||||||
go.opencensus.io v0.22.5 // indirect
|
go.opencensus.io v0.22.5 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -207,8 +207,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
|
||||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
||||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||||
@@ -277,8 +275,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
|||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss=
|
go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss=
|
||||||
go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||||
go.mongodb.org/mongo-driver/v2 v2.4.0 h1:Oq6BmUAAFTzMeh6AonuDlgZMuAuEiUxoAD1koK5MuFo=
|
go.mongodb.org/mongo-driver/v2 v2.4.1 h1:hGDMngUao03OVQ6sgV5csk+RWOIkF+CuLsTPobNMGNI=
|
||||||
go.mongodb.org/mongo-driver/v2 v2.4.0/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI=
|
go.mongodb.org/mongo-driver/v2 v2.4.1/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI=
|
||||||
go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
|
go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
|
||||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
|||||||
7
init.go
7
init.go
@@ -1,13 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"order/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// initServices 初始化服务
|
// initServices 初始化服务
|
||||||
func initServices() error {
|
func initServices() error {
|
||||||
return service.InitServices()
|
// 服务自动初始化,无需手动调用
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// initRoutes 初始化路由
|
// initRoutes 初始化路由
|
||||||
@@ -28,5 +29,5 @@ func initRoutes() {
|
|||||||
paymentGroup.POST("/notify", "order.controller.Order.PaymentNotify")
|
paymentGroup.POST("/notify", "order.controller.Order.PaymentNotify")
|
||||||
paymentGroup.POST("/refund-notify", "order.controller.Order.RefundNotify")
|
paymentGroup.POST("/refund-notify", "order.controller.Order.RefundNotify")
|
||||||
|
|
||||||
g.Log().Info(g.Request().GetCtx(), "路由初始化完成")
|
g.Log().Info(context.Background(), "路由初始化完成")
|
||||||
}
|
}
|
||||||
|
|||||||
17
main.go
17
main.go
@@ -8,26 +8,13 @@ import (
|
|||||||
_ "gitee.com/red-future---jilin-g/common/ragflow" // RAGFlow 客户端自动初始化
|
_ "gitee.com/red-future---jilin-g/common/ragflow" // RAGFlow 客户端自动初始化
|
||||||
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||||
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"order/controller"
|
"order/controller"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
defer jaeger.ShutDown(context.Background())
|
defer jaeger.ShutDown(context.Background())
|
||||||
|
|
||||||
// 初始化服务
|
|
||||||
if err := initServices(); err != nil {
|
|
||||||
g.Log().Fatal(context.Background(), "初始化服务失败:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化路由
|
|
||||||
initRoutes()
|
|
||||||
|
|
||||||
// 注册路由
|
|
||||||
http.RouteRegister([]interface{}{
|
http.RouteRegister([]interface{}{
|
||||||
controller.OrderController,
|
controller.Order,
|
||||||
})
|
})
|
||||||
|
select {}
|
||||||
// 启动服务
|
|
||||||
g.Server().Run()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,3 +204,120 @@ type OrderSummary struct {
|
|||||||
CreatedAt time.Time `json:"created_at"` // 创建时间
|
CreatedAt time.Time `json:"created_at"` // 创建时间
|
||||||
PaidAt *time.Time `json:"paid_at"` // 支付时间
|
PaidAt *time.Time `json:"paid_at"` // 支付时间
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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"` // 签名
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaymentNotifyResp 支付回调响应
|
||||||
|
|
||||||
|
type PaymentNotifyResp struct {
|
||||||
|
Success bool `json:"success"` // 是否成功
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"` // 签名
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefundNotifyResp 退款回调响应
|
||||||
|
|
||||||
|
type RefundNotifyResp struct {
|
||||||
|
Success bool `json:"success"` // 是否成功
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePaymentConfigReq 创建支付配置请求
|
||||||
|
|
||||||
|
type CreatePaymentConfigReq struct {
|
||||||
|
TenantID string `json:"tenant_id" binding:"required"` // 租户ID
|
||||||
|
PayMethod string `json:"pay_method" binding:"required"` // 支付方式:wechat/alipay
|
||||||
|
ConfigName string `json:"config_name" binding:"required"` // 配置名称
|
||||||
|
Remark string `json:"remark"` // 备注
|
||||||
|
IsEnabled bool `json:"is_enabled"` // 是否启用
|
||||||
|
Config map[string]interface{} `json:"config" binding:"required"` // 配置参数
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePaymentConfigReq 更新支付配置请求
|
||||||
|
|
||||||
|
type UpdatePaymentConfigReq struct {
|
||||||
|
ID string `json:"id" binding:"required"` // 配置ID
|
||||||
|
TenantID string `json:"tenant_id" binding:"required"` // 租户ID
|
||||||
|
ConfigName string `json:"config_name" binding:"required"` // 配置名称
|
||||||
|
Remark string `json:"remark"` // 备注
|
||||||
|
IsEnabled bool `json:"is_enabled"` // 是否启用
|
||||||
|
Config map[string]interface{} `json:"config" binding:"required"` // 配置参数
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryPaymentConfigReq 查询支付配置请求
|
||||||
|
|
||||||
|
type QueryPaymentConfigReq struct {
|
||||||
|
TenantID string `json:"tenant_id" binding:"required"` // 租户ID
|
||||||
|
PayMethod string `json:"pay_method"` // 支付方式(可选)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaymentConfigResp 支付配置响应
|
||||||
|
|
||||||
|
type PaymentConfigResp struct {
|
||||||
|
ID string `json:"id"` // 配置ID
|
||||||
|
TenantID string `json:"tenant_id"` // 租户ID
|
||||||
|
PayMethod string `json:"pay_method"` // 支付方式
|
||||||
|
ConfigName string `json:"config_name"` // 配置名称
|
||||||
|
Remark string `json:"remark"` // 备注
|
||||||
|
IsEnabled bool `json:"is_enabled"` // 是否启用
|
||||||
|
Config map[string]interface{} `json:"config"` // 配置参数
|
||||||
|
CreatedAt time.Time `json:"created_at"` // 创建时间
|
||||||
|
UpdatedAt time.Time `json:"updated_at"` // 更新时间
|
||||||
|
}
|
||||||
|
|
||||||
|
// WechatConfig 微信支付配置
|
||||||
|
|
||||||
|
type WechatConfig struct {
|
||||||
|
ID string `json:"id"` // 配置ID
|
||||||
|
TenantID string `json:"tenant_id"` // 租户ID
|
||||||
|
ConfigName string `json:"config_name"` // 配置名称
|
||||||
|
AppID string `json:"app_id"` // 应用ID
|
||||||
|
MchID string `json:"mch_id"` // 商户号
|
||||||
|
APIKey string `json:"api_key"` // API密钥
|
||||||
|
NotifyURL string `json:"notify_url"` // 回调地址
|
||||||
|
ReturnURL string `json:"return_url"` // 返回地址
|
||||||
|
CertPath string `json:"cert_path"` // 证书路径
|
||||||
|
KeyPath string `json:"key_path"` // 密钥路径
|
||||||
|
Sandbox bool `json:"sandbox"` // 是否沙箱环境
|
||||||
|
SupportNative bool `json:"support_native"` // 支持扫码支付
|
||||||
|
SupportJSAPI bool `json:"support_jsapi"` // 支持JSAPI支付
|
||||||
|
SupportAPP bool `json:"support_app"` // 支持APP支付
|
||||||
|
SupportH5 bool `json:"support_h5"` // 支持H5支付
|
||||||
|
GatewayURL string `json:"gateway_url"` // 网关地址
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlipayConfig 支付宝支付配置
|
||||||
|
|
||||||
|
type AlipayConfig struct {
|
||||||
|
ID string `json:"id"` // 配置ID
|
||||||
|
TenantID string `json:"tenant_id"` // 租户ID
|
||||||
|
ConfigName string `json:"config_name"` // 配置名称
|
||||||
|
AppID string `json:"app_id"` // 应用ID
|
||||||
|
NotifyURL string `json:"notify_url"` // 回调地址
|
||||||
|
ReturnURL string `json:"return_url"` // 返回地址
|
||||||
|
AppPrivateKey string `json:"app_private_key"` // 应用私钥
|
||||||
|
AlipayPublicKey string `json:"alipay_public_key"` // 支付宝公钥
|
||||||
|
Sandbox bool `json:"sandbox"` // 是否沙箱环境
|
||||||
|
GatewayURL string `json:"gateway_url"` // 网关地址
|
||||||
|
SupportNative bool `json:"support_native"` // 支持扫码支付
|
||||||
|
SupportJSAPI bool `json:"support_jsapi"` // 支持JSAPI支付
|
||||||
|
SupportAPP bool `json:"support_app"` // 支持APP支付
|
||||||
|
SupportH5 bool `json:"support_h5"` // 支持H5支付
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package entity
|
package entity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,18 +12,18 @@ import (
|
|||||||
// 例如:orders_pending, orders_paid, orders_shipped, orders_completed, orders_cancelled
|
// 例如:orders_pending, orders_paid, orders_shipped, orders_completed, orders_cancelled
|
||||||
|
|
||||||
type OrderBase struct {
|
type OrderBase struct {
|
||||||
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
|
ID bson.ObjectID `bson:"_id,omitempty" json:"id"`
|
||||||
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
||||||
OrderNo string `bson:"order_no" json:"order_no"` // 订单号
|
OrderNo string `bson:"order_no" json:"order_no"` // 订单号
|
||||||
UserID string `bson:"user_id" json:"user_id"` // 用户ID
|
UserID string `bson:"user_id" json:"user_id"` // 用户ID
|
||||||
TotalAmount int64 `bson:"total_amount" json:"total_amount"` // 订单总金额(分)
|
TotalAmount int64 `bson:"total_amount" json:"total_amount"` // 订单总金额(分)
|
||||||
PayAmount int64 `bson:"pay_amount" json:"pay_amount"` // 实付金额(分)
|
PayAmount int64 `bson:"pay_amount" json:"pay_amount"` // 实付金额(分)
|
||||||
OrderType string `bson:"order_type" json:"order_type"` // 订单类型:normal-普通订单
|
OrderType string `bson:"order_type" json:"order_type"` // 订单类型:normal-普通订单
|
||||||
Subject string `bson:"subject" json:"subject"` // 订单标题
|
Subject string `bson:"subject" json:"subject"` // 订单标题
|
||||||
Description string `bson:"description" json:"description"` // 订单描述
|
Description string `bson:"description" json:"description"` // 订单描述
|
||||||
CreatedAt time.Time `bson:"created_at" json:"created_at"` // 创建时间
|
CreatedAt time.Time `bson:"created_at" json:"created_at"` // 创建时间
|
||||||
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"` // 更新时间
|
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"` // 更新时间
|
||||||
ExpiredAt *time.Time `bson:"expired_at,omitempty" json:"expired_at"` // 过期时间
|
ExpiredAt *time.Time `bson:"expired_at,omitempty" json:"expired_at"` // 过期时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// OrderItem 订单商品项
|
// OrderItem 订单商品项
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package entity
|
package entity
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OrderPending 待支付订单
|
// OrderPending 待支付订单
|
||||||
// 对应MongoDB集合:orders_pending
|
// 对应MongoDB集合:orders_pending
|
||||||
// 订单创建后进入此状态
|
// 订单创建后进入此状态
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package entity
|
package entity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PaymentConfig 支付配置
|
// PaymentConfig 支付配置
|
||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
// 支持微信支付和支付宝支付
|
// 支持微信支付和支付宝支付
|
||||||
|
|
||||||
type PaymentConfig struct {
|
type PaymentConfig struct {
|
||||||
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
|
ID bson.ObjectID `bson:"_id,omitempty" json:"id"`
|
||||||
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
||||||
PayMethod string `bson:"pay_method" json:"pay_method"` // 支付方式:wechat/alipay
|
PayMethod string `bson:"pay_method" json:"pay_method"` // 支付方式:wechat/alipay
|
||||||
ConfigName string `bson:"config_name" json:"config_name"` // 配置名称
|
ConfigName string `bson:"config_name" json:"config_name"` // 配置名称
|
||||||
Description string `bson:"description" json:"description"` // 配置描述
|
Description string `bson:"description" json:"description"` // 配置描述
|
||||||
Enabled bool `bson:"enabled" json:"enabled"` // 是否启用
|
Enabled bool `bson:"enabled" json:"enabled"` // 是否启用
|
||||||
|
|
||||||
// 通用配置
|
// 通用配置
|
||||||
AppID string `bson:"app_id" json:"app_id"` // 应用ID
|
AppID string `bson:"app_id" json:"app_id"` // 应用ID
|
||||||
@@ -46,37 +46,37 @@ type PaymentConfig struct {
|
|||||||
// 记录每次支付操作的结果
|
// 记录每次支付操作的结果
|
||||||
|
|
||||||
type PaymentRecord struct {
|
type PaymentRecord struct {
|
||||||
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
|
ID bson.ObjectID `bson:"_id,omitempty" json:"id"`
|
||||||
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
||||||
OrderID primitive.ObjectID `bson:"order_id" json:"order_id"` // 订单ID
|
OrderID bson.ObjectID `bson:"order_id" json:"order_id"` // 订单ID
|
||||||
OrderNo string `bson:"order_no" json:"order_no"` // 订单号
|
OrderNo string `bson:"order_no" json:"order_no"` // 订单号
|
||||||
PayMethod string `bson:"pay_method" json:"pay_method"` // 支付方式
|
PayMethod string `bson:"pay_method" json:"pay_method"` // 支付方式
|
||||||
PayType string `bson:"pay_type" json:"pay_type"` // 支付类型
|
PayType string `bson:"pay_type" json:"pay_type"` // 支付类型
|
||||||
Amount int64 `bson:"amount" json:"amount"` // 支付金额(分)
|
Amount int64 `bson:"amount" json:"amount"` // 支付金额(分)
|
||||||
TransactionID string `bson:"transaction_id" json:"transaction_id"` // 支付平台交易号
|
TransactionID string `bson:"transaction_id" json:"transaction_id"` // 支付平台交易号
|
||||||
OutTradeNo string `bson:"out_trade_no" json:"out_trade_no"` // 商户订单号
|
OutTradeNo string `bson:"out_trade_no" json:"out_trade_no"` // 商户订单号
|
||||||
TradeNo string `bson:"trade_no" json:"trade_no"` // 交易号
|
TradeNo string `bson:"trade_no" json:"trade_no"` // 交易号
|
||||||
PrepayID string `bson:"prepay_id,omitempty" json:"prepay_id"` // 预支付ID
|
PrepayID string `bson:"prepay_id,omitempty" json:"prepay_id"` // 预支付ID
|
||||||
Status string `bson:"status" json:"status"` // 支付状态:success/failed
|
Status string `bson:"status" json:"status"` // 支付状态:success/failed
|
||||||
ErrorMsg string `bson:"error_msg,omitempty" json:"error_msg"` // 错误信息
|
ErrorMsg string `bson:"error_msg,omitempty" json:"error_msg"` // 错误信息
|
||||||
CreatedAt int64 `bson:"created_at" json:"created_at"` // 创建时间
|
CreatedAt int64 `bson:"created_at" json:"created_at"` // 创建时间
|
||||||
UpdatedAt int64 `bson:"updated_at" json:"updated_at"` // 更新时间
|
UpdatedAt int64 `bson:"updated_at" json:"updated_at"` // 更新时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefundRecord 退款记录
|
// RefundRecord 退款记录
|
||||||
// 记录每次退款操作的结果
|
// 记录每次退款操作的结果
|
||||||
|
|
||||||
type RefundRecord struct {
|
type RefundRecord struct {
|
||||||
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
|
ID bson.ObjectID `bson:"_id,omitempty" json:"id"`
|
||||||
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
TenantID string `bson:"tenant_id" json:"tenant_id"` // 租户ID
|
||||||
OrderID primitive.ObjectID `bson:"order_id" json:"order_id"` // 订单ID
|
OrderID bson.ObjectID `bson:"order_id" json:"order_id"` // 订单ID
|
||||||
OrderNo string `bson:"order_no" json:"order_no"` // 订单号
|
OrderNo string `bson:"order_no" json:"order_no"` // 订单号
|
||||||
RefundNo string `bson:"refund_no" json:"refund_no"` // 退款单号
|
RefundNo string `bson:"refund_no" json:"refund_no"` // 退款单号
|
||||||
RefundID string `bson:"refund_id" json:"refund_id"` // 退款ID
|
RefundID string `bson:"refund_id" json:"refund_id"` // 退款ID
|
||||||
RefundAmount int64 `bson:"refund_amount" json:"refund_amount"` // 退款金额(分)
|
RefundAmount int64 `bson:"refund_amount" json:"refund_amount"` // 退款金额(分)
|
||||||
Reason string `bson:"reason" json:"reason"` // 退款原因
|
Reason string `bson:"reason" json:"reason"` // 退款原因
|
||||||
Status string `bson:"status" json:"status"` // 退款状态:success/failed
|
Status string `bson:"status" json:"status"` // 退款状态:success/failed
|
||||||
ErrorMsg string `bson:"error_msg,omitempty" json:"error_msg"` // 错误信息
|
ErrorMsg string `bson:"error_msg,omitempty" json:"error_msg"` // 错误信息
|
||||||
CreatedAt int64 `bson:"created_at" json:"created_at"` // 创建时间
|
CreatedAt int64 `bson:"created_at" json:"created_at"` // 创建时间
|
||||||
UpdatedAt int64 `bson:"updated_at" json:"updated_at"` // 更新时间
|
UpdatedAt int64 `bson:"updated_at" json:"updated_at"` // 更新时间
|
||||||
}
|
}
|
||||||
|
|||||||
147
service/order.go
147
service/order.go
@@ -5,31 +5,70 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"order/consts"
|
||||||
"order/dao"
|
"order/dao"
|
||||||
"order/model/dto"
|
"order/model/dto"
|
||||||
"order/model/entity"
|
"order/model/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OrderService 订单服务
|
type order struct{}
|
||||||
|
|
||||||
type OrderService struct {
|
// Order 订单服务
|
||||||
orderDao *dao.OrderDao
|
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 创建订单服务实例
|
// convertOrderItems 转换订单商品项
|
||||||
func NewOrderService(orderDao *dao.OrderDao) *OrderService {
|
func convertOrderItems(items []entity.OrderItem) []dto.OrderItem {
|
||||||
return &OrderService{
|
var result []dto.OrderItem
|
||||||
orderDao: orderDao,
|
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 创建订单
|
// 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. 参数验证
|
// 1. 参数验证
|
||||||
if req.TenantID == "" || req.UserID == "" || req.Subject == "" {
|
if req.TenantID == "" || req.UserID == "" || req.Subject == "" {
|
||||||
return nil, errors.New("必填参数不能为空")
|
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 {
|
if item.Price <= 0 || item.Quantity <= 0 {
|
||||||
return nil, fmt.Errorf("商品价格或数量无效: %s", item.ProductName)
|
return nil, fmt.Errorf("商品价格或数量无效: %s", item.ProductName)
|
||||||
}
|
}
|
||||||
item.TotalPrice = item.Price * int64(item.Quantity)
|
totalPrice := item.Price * int64(item.Quantity)
|
||||||
totalAmount += item.TotalPrice
|
totalAmount += totalPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
if totalAmount <= 0 {
|
if totalAmount <= 0 {
|
||||||
@@ -73,13 +112,13 @@ func (s *OrderService) CreateOrder(ctx context.Context, req *dto.CreateOrderReq)
|
|||||||
Description: req.Description,
|
Description: req.Description,
|
||||||
ExpiredAt: &expiredAt,
|
ExpiredAt: &expiredAt,
|
||||||
},
|
},
|
||||||
OrderItems: gconv.Slice[*entity.OrderItem](req.OrderItems),
|
OrderItems: convertOrderItemsFromDTO(req.OrderItems),
|
||||||
ShippingInfo: (*entity.ShippingInfo)(&req.ShippingInfo),
|
ShippingInfo: (*entity.ShippingInfo)(&req.ShippingInfo),
|
||||||
PayInfo: entity.PayInfo{},
|
PayInfo: entity.PayInfo{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 保存订单
|
// 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)
|
return nil, fmt.Errorf("创建订单失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,21 +134,21 @@ func (s *OrderService) CreateOrder(ctx context.Context, req *dto.CreateOrderReq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generateOrderNo 生成订单号
|
// generateOrderNo 生成订单号
|
||||||
func (s *OrderService) generateOrderNo(tenantID string) string {
|
func (s *order) generateOrderNo(tenantID string) string {
|
||||||
timestamp := time.Now().Format("20060102150405")
|
timestamp := time.Now().Format("20060102150405")
|
||||||
random := rand.Intn(10000)
|
random := rand.Intn(10000)
|
||||||
return fmt.Sprintf("%s%s%04d", tenantID, timestamp, random)
|
return fmt.Sprintf("%s%s%04d", tenantID, timestamp, random)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryOrder 查询订单详情
|
// 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. 参数验证
|
// 1. 参数验证
|
||||||
if req.TenantID == "" || req.OrderNo == "" {
|
if req.TenantID == "" || req.OrderNo == "" {
|
||||||
return nil, errors.New("必填参数不能为空")
|
return nil, errors.New("必填参数不能为空")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询订单
|
// 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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -122,19 +161,19 @@ func (s *OrderService) QueryOrder(ctx context.Context, req *dto.QueryOrderReq) (
|
|||||||
var resp dto.QueryOrderResp
|
var resp dto.QueryOrderResp
|
||||||
|
|
||||||
switch status {
|
switch status {
|
||||||
case entity.OrderStatusPending:
|
case consts.OrderStatusPending:
|
||||||
if pendingOrder, ok := order.(*entity.OrderPending); ok {
|
if pendingOrder, ok := order.(*entity.OrderPending); ok {
|
||||||
resp.Order = s.convertPendingOrderToDetail(pendingOrder)
|
resp.Order = s.convertPendingOrderToDetail(pendingOrder)
|
||||||
}
|
}
|
||||||
case entity.OrderStatusPaid:
|
case consts.OrderStatusPaid:
|
||||||
if paidOrder, ok := order.(*entity.OrderPaid); ok {
|
if paidOrder, ok := order.(*entity.OrderPaid); ok {
|
||||||
resp.Order = s.convertPaidOrderToDetail(paidOrder)
|
resp.Order = s.convertPaidOrderToDetail(paidOrder)
|
||||||
}
|
}
|
||||||
case entity.OrderStatusShipped:
|
case consts.OrderStatusShipped:
|
||||||
if shippedOrder, ok := order.(*entity.OrderShipped); ok {
|
if shippedOrder, ok := order.(*entity.OrderShipped); ok {
|
||||||
resp.Order = s.convertShippedOrderToDetail(shippedOrder)
|
resp.Order = s.convertShippedOrderToDetail(shippedOrder)
|
||||||
}
|
}
|
||||||
case entity.OrderStatusCompleted:
|
case consts.OrderStatusCompleted:
|
||||||
if completedOrder, ok := order.(*entity.OrderCompleted); ok {
|
if completedOrder, ok := order.(*entity.OrderCompleted); ok {
|
||||||
resp.Order = s.convertCompletedOrderToDetail(completedOrder)
|
resp.Order = s.convertCompletedOrderToDetail(completedOrder)
|
||||||
}
|
}
|
||||||
@@ -146,7 +185,7 @@ func (s *OrderService) QueryOrder(ctx context.Context, req *dto.QueryOrderReq) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertPendingOrderToDetail 转换待支付订单为详情
|
// convertPendingOrderToDetail 转换待支付订单为详情
|
||||||
func (s *OrderService) convertPendingOrderToDetail(order *entity.OrderPending) dto.OrderDetail {
|
func (s *order) convertPendingOrderToDetail(order *entity.OrderPending) dto.OrderDetail {
|
||||||
return dto.OrderDetail{
|
return dto.OrderDetail{
|
||||||
ID: order.ID.Hex(),
|
ID: order.ID.Hex(),
|
||||||
TenantID: order.TenantID,
|
TenantID: order.TenantID,
|
||||||
@@ -154,13 +193,13 @@ func (s *OrderService) convertPendingOrderToDetail(order *entity.OrderPending) d
|
|||||||
UserID: order.UserID,
|
UserID: order.UserID,
|
||||||
TotalAmount: order.TotalAmount,
|
TotalAmount: order.TotalAmount,
|
||||||
PayAmount: order.PayAmount,
|
PayAmount: order.PayAmount,
|
||||||
Status: string(entity.OrderStatusPending),
|
Status: string(consts.OrderStatusPending),
|
||||||
PayMethod: order.PayMethod,
|
PayMethod: order.PayMethod,
|
||||||
PayStatus: "unpaid",
|
PayStatus: "unpaid",
|
||||||
OrderType: order.OrderType,
|
OrderType: order.OrderType,
|
||||||
Subject: order.Subject,
|
Subject: order.Subject,
|
||||||
Description: order.Description,
|
Description: order.Description,
|
||||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
OrderItems: convertOrderItems(order.OrderItems),
|
||||||
ShippingInfo: dto.ShippingInfo{
|
ShippingInfo: dto.ShippingInfo{
|
||||||
Consignee: order.ShippingInfo.Consignee,
|
Consignee: order.ShippingInfo.Consignee,
|
||||||
Phone: order.ShippingInfo.Phone,
|
Phone: order.ShippingInfo.Phone,
|
||||||
@@ -183,7 +222,7 @@ func (s *OrderService) convertPendingOrderToDetail(order *entity.OrderPending) d
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertPaidOrderToDetail 转换已支付订单为详情
|
// convertPaidOrderToDetail 转换已支付订单为详情
|
||||||
func (s *OrderService) convertPaidOrderToDetail(order *entity.OrderPaid) dto.OrderDetail {
|
func (s *order) convertPaidOrderToDetail(order *entity.OrderPaid) dto.OrderDetail {
|
||||||
return dto.OrderDetail{
|
return dto.OrderDetail{
|
||||||
ID: order.ID.Hex(),
|
ID: order.ID.Hex(),
|
||||||
TenantID: order.TenantID,
|
TenantID: order.TenantID,
|
||||||
@@ -191,13 +230,13 @@ func (s *OrderService) convertPaidOrderToDetail(order *entity.OrderPaid) dto.Ord
|
|||||||
UserID: order.UserID,
|
UserID: order.UserID,
|
||||||
TotalAmount: order.TotalAmount,
|
TotalAmount: order.TotalAmount,
|
||||||
PayAmount: order.PayAmount,
|
PayAmount: order.PayAmount,
|
||||||
Status: string(entity.OrderStatusPaid),
|
Status: string(consts.OrderStatusPaid),
|
||||||
PayMethod: order.PayMethod,
|
PayMethod: order.PayMethod,
|
||||||
PayStatus: "paid",
|
PayStatus: "paid",
|
||||||
OrderType: order.OrderType,
|
OrderType: order.OrderType,
|
||||||
Subject: order.Subject,
|
Subject: order.Subject,
|
||||||
Description: order.Description,
|
Description: order.Description,
|
||||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
OrderItems: convertOrderItems(order.OrderItems),
|
||||||
ShippingInfo: dto.ShippingInfo{
|
ShippingInfo: dto.ShippingInfo{
|
||||||
Consignee: order.ShippingInfo.Consignee,
|
Consignee: order.ShippingInfo.Consignee,
|
||||||
Phone: order.ShippingInfo.Phone,
|
Phone: order.ShippingInfo.Phone,
|
||||||
@@ -218,7 +257,7 @@ func (s *OrderService) convertPaidOrderToDetail(order *entity.OrderPaid) dto.Ord
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertShippedOrderToDetail 转换已发货订单为详情
|
// convertShippedOrderToDetail 转换已发货订单为详情
|
||||||
func (s *OrderService) convertShippedOrderToDetail(order *entity.OrderShipped) dto.OrderDetail {
|
func (s *order) convertShippedOrderToDetail(order *entity.OrderShipped) dto.OrderDetail {
|
||||||
return dto.OrderDetail{
|
return dto.OrderDetail{
|
||||||
ID: order.ID.Hex(),
|
ID: order.ID.Hex(),
|
||||||
TenantID: order.TenantID,
|
TenantID: order.TenantID,
|
||||||
@@ -226,13 +265,13 @@ func (s *OrderService) convertShippedOrderToDetail(order *entity.OrderShipped) d
|
|||||||
UserID: order.UserID,
|
UserID: order.UserID,
|
||||||
TotalAmount: order.TotalAmount,
|
TotalAmount: order.TotalAmount,
|
||||||
PayAmount: order.PayAmount,
|
PayAmount: order.PayAmount,
|
||||||
Status: string(entity.OrderStatusShipped),
|
Status: string(consts.OrderStatusShipped),
|
||||||
PayMethod: order.PayMethod,
|
PayMethod: order.PayMethod,
|
||||||
PayStatus: "paid",
|
PayStatus: "paid",
|
||||||
OrderType: order.OrderType,
|
OrderType: order.OrderType,
|
||||||
Subject: order.Subject,
|
Subject: order.Subject,
|
||||||
Description: order.Description,
|
Description: order.Description,
|
||||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
OrderItems: convertOrderItems(order.OrderItems),
|
||||||
ShippingInfo: dto.ShippingInfo{
|
ShippingInfo: dto.ShippingInfo{
|
||||||
Consignee: order.ShippingInfo.Consignee,
|
Consignee: order.ShippingInfo.Consignee,
|
||||||
Phone: order.ShippingInfo.Phone,
|
Phone: order.ShippingInfo.Phone,
|
||||||
@@ -249,7 +288,7 @@ func (s *OrderService) convertShippedOrderToDetail(order *entity.OrderShipped) d
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertCompletedOrderToDetail 转换已完成订单为详情
|
// convertCompletedOrderToDetail 转换已完成订单为详情
|
||||||
func (s *OrderService) convertCompletedOrderToDetail(order *entity.OrderCompleted) dto.OrderDetail {
|
func (s *order) convertCompletedOrderToDetail(order *entity.OrderCompleted) dto.OrderDetail {
|
||||||
return dto.OrderDetail{
|
return dto.OrderDetail{
|
||||||
ID: order.ID.Hex(),
|
ID: order.ID.Hex(),
|
||||||
TenantID: order.TenantID,
|
TenantID: order.TenantID,
|
||||||
@@ -257,13 +296,13 @@ func (s *OrderService) convertCompletedOrderToDetail(order *entity.OrderComplete
|
|||||||
UserID: order.UserID,
|
UserID: order.UserID,
|
||||||
TotalAmount: order.TotalAmount,
|
TotalAmount: order.TotalAmount,
|
||||||
PayAmount: order.PayAmount,
|
PayAmount: order.PayAmount,
|
||||||
Status: string(entity.OrderStatusCompleted),
|
Status: string(consts.OrderStatusCompleted),
|
||||||
PayMethod: order.PayMethod,
|
PayMethod: order.PayMethod,
|
||||||
PayStatus: "paid",
|
PayStatus: "paid",
|
||||||
OrderType: order.OrderType,
|
OrderType: order.OrderType,
|
||||||
Subject: order.Subject,
|
Subject: order.Subject,
|
||||||
Description: order.Description,
|
Description: order.Description,
|
||||||
OrderItems: s.convertOrderItems(order.OrderItems),
|
OrderItems: convertOrderItems(order.OrderItems),
|
||||||
ShippingInfo: dto.ShippingInfo{
|
ShippingInfo: dto.ShippingInfo{
|
||||||
Consignee: order.ShippingInfo.Consignee,
|
Consignee: order.ShippingInfo.Consignee,
|
||||||
Phone: order.ShippingInfo.Phone,
|
Phone: order.ShippingInfo.Phone,
|
||||||
@@ -280,7 +319,7 @@ func (s *OrderService) convertCompletedOrderToDetail(order *entity.OrderComplete
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertOrderItems 转换订单商品项
|
// convertOrderItems 转换订单商品项
|
||||||
func (s *OrderService) convertOrderItems(items []*entity.OrderItem) []dto.OrderItem {
|
func (s *order) convertOrderItems(items []*entity.OrderItem) []dto.OrderItem {
|
||||||
var result []dto.OrderItem
|
var result []dto.OrderItem
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
result = append(result, dto.OrderItem{
|
result = append(result, dto.OrderItem{
|
||||||
@@ -296,14 +335,14 @@ func (s *OrderService) convertOrderItems(items []*entity.OrderItem) []dto.OrderI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CancelOrder 取消订单
|
// 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. 参数验证
|
// 1. 参数验证
|
||||||
if req.TenantID == "" || req.OrderNo == "" {
|
if req.TenantID == "" || req.OrderNo == "" {
|
||||||
return nil, errors.New("必填参数不能为空")
|
return nil, errors.New("必填参数不能为空")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询订单
|
// 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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -313,7 +352,7 @@ func (s *OrderService) CancelOrder(ctx context.Context, req *dto.CancelOrderReq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 检查订单状态(只有待支付订单可以取消)
|
// 3. 检查订单状态(只有待支付订单可以取消)
|
||||||
if status != entity.OrderStatusPending {
|
if status != consts.OrderStatusPending {
|
||||||
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,21 +361,21 @@ func (s *OrderService) CancelOrder(ctx context.Context, req *dto.CancelOrderReq)
|
|||||||
"cancel_reason": req.Reason,
|
"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)
|
return nil, fmt.Errorf("取消订单失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 返回结果
|
// 5. 返回结果
|
||||||
resp := &dto.CancelOrderResp{
|
resp := &dto.CancelOrderResp{
|
||||||
OrderNo: req.OrderNo,
|
OrderNo: req.OrderNo,
|
||||||
Status: string(entity.OrderStatusCancelled),
|
Status: string(consts.OrderStatusCancelled),
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListOrders 查询订单列表
|
// 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. 参数验证
|
// 1. 参数验证
|
||||||
if req.TenantID == "" {
|
if req.TenantID == "" {
|
||||||
return nil, errors.New("租户ID不能为空")
|
return nil, errors.New("租户ID不能为空")
|
||||||
@@ -350,15 +389,15 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. 根据状态查询订单列表
|
// 2. 根据状态查询订单列表
|
||||||
var status entity.OrderStatus
|
var status consts.OrderStatus
|
||||||
if req.Status != "" {
|
if req.Status != "" {
|
||||||
status = entity.OrderStatus(req.Status)
|
status = consts.OrderStatus(req.Status)
|
||||||
} else {
|
} 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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("查询订单列表失败: %w", err)
|
return nil, fmt.Errorf("查询订单列表失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -367,7 +406,7 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
|||||||
var orderSummaries []dto.OrderSummary
|
var orderSummaries []dto.OrderSummary
|
||||||
|
|
||||||
switch status {
|
switch status {
|
||||||
case entity.OrderStatusPending:
|
case consts.OrderStatusPending:
|
||||||
if pendingOrders, ok := orders.([]entity.OrderPending); ok {
|
if pendingOrders, ok := orders.([]entity.OrderPending); ok {
|
||||||
for _, order := range pendingOrders {
|
for _, order := range pendingOrders {
|
||||||
orderSummaries = append(orderSummaries, dto.OrderSummary{
|
orderSummaries = append(orderSummaries, dto.OrderSummary{
|
||||||
@@ -375,13 +414,13 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
|||||||
OrderNo: order.OrderNo,
|
OrderNo: order.OrderNo,
|
||||||
TotalAmount: order.TotalAmount,
|
TotalAmount: order.TotalAmount,
|
||||||
PayAmount: order.PayAmount,
|
PayAmount: order.PayAmount,
|
||||||
Status: string(entity.OrderStatusPending),
|
Status: string(consts.OrderStatusPending),
|
||||||
Subject: order.Subject,
|
Subject: order.Subject,
|
||||||
CreatedAt: order.CreatedAt,
|
CreatedAt: order.CreatedAt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case entity.OrderStatusPaid:
|
case consts.OrderStatusPaid:
|
||||||
if paidOrders, ok := orders.([]entity.OrderPaid); ok {
|
if paidOrders, ok := orders.([]entity.OrderPaid); ok {
|
||||||
for _, order := range paidOrders {
|
for _, order := range paidOrders {
|
||||||
orderSummaries = append(orderSummaries, dto.OrderSummary{
|
orderSummaries = append(orderSummaries, dto.OrderSummary{
|
||||||
@@ -389,7 +428,7 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
|||||||
OrderNo: order.OrderNo,
|
OrderNo: order.OrderNo,
|
||||||
TotalAmount: order.TotalAmount,
|
TotalAmount: order.TotalAmount,
|
||||||
PayAmount: order.PayAmount,
|
PayAmount: order.PayAmount,
|
||||||
Status: string(entity.OrderStatusPaid),
|
Status: string(consts.OrderStatusPaid),
|
||||||
Subject: order.Subject,
|
Subject: order.Subject,
|
||||||
CreatedAt: order.CreatedAt,
|
CreatedAt: order.CreatedAt,
|
||||||
PaidAt: &order.PaidAt,
|
PaidAt: &order.PaidAt,
|
||||||
@@ -411,9 +450,9 @@ func (s *OrderService) ListOrders(ctx context.Context, req *dto.ListOrdersReq) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ProcessExpiredOrders 处理过期订单
|
// 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 {
|
if err != nil {
|
||||||
return fmt.Errorf("获取过期订单失败: %w", err)
|
return fmt.Errorf("获取过期订单失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -424,7 +463,7 @@ func (s *OrderService) ProcessExpiredOrders(ctx context.Context, tenantID string
|
|||||||
"cancel_reason": "订单超时自动取消",
|
"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)
|
fmt.Printf("取消过期订单失败: %s, 错误: %v\n", order.OrderNo, err)
|
||||||
}
|
}
|
||||||
@@ -434,6 +473,6 @@ func (s *OrderService) ProcessExpiredOrders(ctx context.Context, tenantID string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePayInfo 更新支付信息
|
// UpdatePayInfo 更新支付信息
|
||||||
func (s *OrderService) UpdatePayInfo(ctx context.Context, tenantID, orderNo string, payInfo entity.PayInfo) error {
|
func (s *order) UpdatePayInfo(ctx context.Context, tenantID, orderNo string, payInfo entity.PayInfo) error {
|
||||||
return s.orderDao.UpdatePayInfo(ctx, tenantID, orderNo, payInfo)
|
return dao.Order.UpdatePayInfo(ctx, tenantID, orderNo, payInfo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,45 +7,27 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
"order/consts"
|
||||||
"order/dao"
|
"order/dao"
|
||||||
"order/model/dto"
|
"order/model/dto"
|
||||||
"order/model/entity"
|
"order/model/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PaymentService 支付服务
|
type payment struct{}
|
||||||
|
|
||||||
type PaymentService struct {
|
// Payment 支付服务
|
||||||
orderDao *dao.OrderDao
|
var Payment = new(payment)
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PayOrder 支付订单
|
// 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. 参数验证
|
// 1. 参数验证
|
||||||
if req.TenantID == "" || req.OrderNo == "" || req.PayMethod == "" || req.PayType == "" {
|
if req.TenantID == "" || req.OrderNo == "" || req.PayMethod == "" || req.PayType == "" {
|
||||||
return nil, errors.New("必填参数不能为空")
|
return nil, errors.New("必填参数不能为空")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询订单
|
// 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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -55,7 +37,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 验证订单状态(只有待支付订单可以支付)
|
// 3. 验证订单状态(只有待支付订单可以支付)
|
||||||
if status != entity.OrderStatusPending {
|
if status != consts.OrderStatusPending {
|
||||||
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +47,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. 获取支付配置
|
// 4. 获取支付配置
|
||||||
paymentConfig, err := s.paymentConfigDao.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
|
paymentConfig, err := dao.PaymentConfig.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("获取支付配置失败: %w", err)
|
return nil, fmt.Errorf("获取支付配置失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -92,7 +74,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
|||||||
Status: "pending",
|
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)
|
return nil, fmt.Errorf("创建支付记录失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +88,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
|||||||
APPParams: payResp.APPParams,
|
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)
|
return nil, fmt.Errorf("更新订单支付信息失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +106,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
|
|||||||
}
|
}
|
||||||
|
|
||||||
// callThirdPartyPayment 调用第三方支付接口
|
// 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 生成商户订单号
|
// generateOutTradeNo 生成商户订单号
|
||||||
func (s *PaymentService) generateOutTradeNo(tenantID string) string {
|
func (s *payment) generateOutTradeNo(tenantID string) string {
|
||||||
timestamp := time.Now().Format("20060102150405")
|
timestamp := time.Now().Format("20060102150405")
|
||||||
random := rand.Intn(10000)
|
random := rand.Intn(10000)
|
||||||
return fmt.Sprintf("%s%s%04d", tenantID, timestamp, random)
|
return fmt.Sprintf("%s%s%04d", tenantID, timestamp, random)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateNonceStr 生成随机字符串
|
// generateNonceStr 生成随机字符串
|
||||||
func (s *PaymentService) generateNonceStr() string {
|
func (s *payment) generateNonceStr() string {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
b := make([]byte, 16)
|
b := make([]byte, 16)
|
||||||
for i := range b {
|
for i := range b {
|
||||||
@@ -185,14 +167,14 @@ func (s *PaymentService) generateNonceStr() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandlePaymentNotify 处理支付回调
|
// HandlePaymentNotify 处理支付回调
|
||||||
func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNotifyReq) error {
|
func (s *payment) HandlePaymentNotify(ctx context.Context, req *dto.PaymentNotifyReq) error {
|
||||||
// 1. 验证回调签名
|
// 1. 验证回调签名
|
||||||
if !s.verifyNotifySignature(req) {
|
if !s.verifyNotifySignature(req) {
|
||||||
return errors.New("签名验证失败")
|
return errors.New("签名验证失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询支付记录
|
// 2. 查询支付记录
|
||||||
paymentRecord, err := s.paymentRecordDao.GetByOrderNo(ctx, req.TenantID, req.OrderNo)
|
paymentRecord, err := dao.PaymentRecord.GetByOrderNo(ctx, req.TenantID, req.OrderNo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("查询支付记录失败: %w", err)
|
return fmt.Errorf("查询支付记录失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -202,7 +184,7 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 更新支付记录状态
|
// 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)
|
return fmt.Errorf("更新支付记录失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +197,7 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
|
|||||||
"payment_channel": req.PayMethod,
|
"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)
|
return fmt.Errorf("更新订单状态失败: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,34 +205,22 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
|
|||||||
return nil
|
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 验证回调签名
|
// verifyNotifySignature 验证回调签名
|
||||||
func (s *PaymentService) verifyNotifySignature(req *PaymentNotifyReq) bool {
|
func (s *payment) verifyNotifySignature(req *dto.PaymentNotifyReq) bool {
|
||||||
// 这里应该是实际的签名验证逻辑
|
// 这里应该是实际的签名验证逻辑
|
||||||
// 为了演示,我们总是返回true
|
// 为了演示,我们总是返回true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefundOrder 退款
|
// 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. 参数验证
|
// 1. 参数验证
|
||||||
if req.TenantID == "" || req.OrderNo == "" || req.RefundAmount <= 0 {
|
if req.TenantID == "" || req.OrderNo == "" || req.RefundAmount <= 0 {
|
||||||
return nil, errors.New("必填参数不能为空")
|
return nil, errors.New("必填参数不能为空")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询订单
|
// 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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("获取订单失败: %w", err)
|
return nil, fmt.Errorf("获取订单失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -260,7 +230,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 验证订单状态(只有已支付订单可以退款)
|
// 3. 验证订单状态(只有已支付订单可以退款)
|
||||||
if status != entity.OrderStatusPaid {
|
if status != consts.OrderStatusPaid {
|
||||||
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +261,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
|||||||
Status: "pending",
|
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)
|
return nil, fmt.Errorf("创建退款记录失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +271,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
|||||||
"refund_reason": req.Reason,
|
"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)
|
return nil, fmt.Errorf("更新订单状态失败: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,7 +287,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// callThirdPartyRefund 调用第三方退款接口
|
// 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 生成退款单号
|
// generateRefundNo 生成退款单号
|
||||||
func (s *PaymentService) generateRefundNo(tenantID string) string {
|
func (s *payment) generateRefundNo(tenantID string) string {
|
||||||
timestamp := time.Now().Format("20060102150405")
|
timestamp := time.Now().Format("20060102150405")
|
||||||
random := rand.Intn(10000)
|
random := rand.Intn(10000)
|
||||||
return fmt.Sprintf("R%s%s%04d", tenantID, timestamp, random)
|
return fmt.Sprintf("R%s%s%04d", tenantID, timestamp, random)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleRefundNotify 处理退款回调
|
// HandleRefundNotify 处理退款回调
|
||||||
func (s *PaymentService) HandleRefundNotify(ctx context.Context, req *RefundNotifyReq) error {
|
func (s *payment) HandleRefundNotify(ctx context.Context, req *dto.RefundNotifyReq) error {
|
||||||
// 1. 验证回调签名
|
// 1. 验证回调签名
|
||||||
if !s.verifyRefundNotifySignature(req) {
|
if !s.verifyRefundNotifySignature(req) {
|
||||||
return errors.New("签名验证失败")
|
return errors.New("签名验证失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询退款记录
|
// 2. 查询退款记录
|
||||||
refundRecord, err := s.refundRecordDao.GetByRefundNo(ctx, req.TenantID, req.RefundNo)
|
refundRecord, err := dao.RefundRecord.GetByRefundNo(ctx, req.TenantID, req.RefundNo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("查询退款记录失败: %w", err)
|
return fmt.Errorf("查询退款记录失败: %w", err)
|
||||||
}
|
}
|
||||||
@@ -362,25 +332,15 @@ func (s *PaymentService) HandleRefundNotify(ctx context.Context, req *RefundNoti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 更新退款记录状态
|
// 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 fmt.Errorf("更新退款记录失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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 验证退款回调签名
|
// verifyRefundNotifySignature 验证退款回调签名
|
||||||
func (s *PaymentService) verifyRefundNotifySignature(req *RefundNotifyReq) bool {
|
func (s *payment) verifyRefundNotifySignature(req *dto.RefundNotifyReq) bool {
|
||||||
// 这里应该是实际的签名验证逻辑
|
// 这里应该是实际的签名验证逻辑
|
||||||
// 为了演示,我们总是返回true
|
// 为了演示,我们总是返回true
|
||||||
return 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