初始化项目

This commit is contained in:
2025-12-10 13:51:09 +08:00
parent 3c55577df8
commit 0486f468d6
19 changed files with 1078 additions and 1010 deletions

View File

@@ -7,45 +7,27 @@ import (
"math/rand"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/v2/bson"
"order/consts"
"order/dao"
"order/model/dto"
"order/model/entity"
)
// PaymentService 支付服务
type payment struct{}
type PaymentService struct {
orderDao *dao.OrderDao
paymentConfigDao *dao.PaymentConfigDao
paymentRecordDao *dao.PaymentRecordDao
refundRecordDao *dao.RefundRecordDao
}
// NewPaymentService 创建支付服务实例
func NewPaymentService(
orderDao *dao.OrderDao,
paymentConfigDao *dao.PaymentConfigDao,
paymentRecordDao *dao.PaymentRecordDao,
refundRecordDao *dao.RefundRecordDao,
) *PaymentService {
return &PaymentService{
orderDao: orderDao,
paymentConfigDao: paymentConfigDao,
paymentRecordDao: paymentRecordDao,
refundRecordDao: refundRecordDao,
}
}
// Payment 支付服务
var Payment = new(payment)
// PayOrder 支付订单
func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*dto.PayOrderResp, error) {
func (s *payment) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*dto.PayOrderResp, error) {
// 1. 参数验证
if req.TenantID == "" || req.OrderNo == "" || req.PayMethod == "" || req.PayType == "" {
return nil, errors.New("必填参数不能为空")
}
// 2. 查询订单
order, status, err := s.orderDao.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
order, status, err := dao.Order.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
if err != nil {
return nil, fmt.Errorf("获取订单失败: %w", err)
}
@@ -55,7 +37,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
}
// 3. 验证订单状态(只有待支付订单可以支付)
if status != entity.OrderStatusPending {
if status != consts.OrderStatusPending {
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
}
@@ -65,7 +47,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
}
// 4. 获取支付配置
paymentConfig, err := s.paymentConfigDao.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
paymentConfig, err := dao.PaymentConfig.GetByTenantAndMethod(ctx, req.TenantID, req.PayMethod)
if err != nil {
return nil, fmt.Errorf("获取支付配置失败: %w", err)
}
@@ -92,7 +74,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
Status: "pending",
}
if err := s.paymentRecordDao.Create(ctx, paymentRecord); err != nil {
if err := dao.PaymentRecord.Create(ctx, paymentRecord); err != nil {
return nil, fmt.Errorf("创建支付记录失败: %w", err)
}
@@ -106,7 +88,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
APPParams: payResp.APPParams,
}
if err := s.orderDao.UpdatePayInfo(ctx, req.TenantID, req.OrderNo, payInfo); err != nil {
if err := dao.Order.UpdatePayInfo(ctx, req.TenantID, req.OrderNo, payInfo); err != nil {
return nil, fmt.Errorf("更新订单支付信息失败: %w", err)
}
@@ -124,7 +106,7 @@ func (s *PaymentService) PayOrder(ctx context.Context, req *dto.PayOrderReq) (*d
}
// callThirdPartyPayment 调用第三方支付接口
func (s *PaymentService) callThirdPartyPayment(ctx context.Context, config *entity.PaymentConfig, req *dto.PayOrderReq, order *entity.OrderPending) (*PaymentResponse, error) {
func (s *payment) callThirdPartyPayment(ctx context.Context, config *entity.PaymentConfig, req *dto.PayOrderReq, order *entity.OrderPending) (*PaymentResponse, error) {
// 这里应该是实际的第三方支付接口调用
// 为了演示,我们返回模拟数据
@@ -168,14 +150,14 @@ type PaymentResponse struct {
}
// generateOutTradeNo 生成商户订单号
func (s *PaymentService) generateOutTradeNo(tenantID string) string {
func (s *payment) generateOutTradeNo(tenantID string) string {
timestamp := time.Now().Format("20060102150405")
random := rand.Intn(10000)
return fmt.Sprintf("%s%s%04d", tenantID, timestamp, random)
}
// generateNonceStr 生成随机字符串
func (s *PaymentService) generateNonceStr() string {
func (s *payment) generateNonceStr() string {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, 16)
for i := range b {
@@ -185,14 +167,14 @@ func (s *PaymentService) generateNonceStr() string {
}
// HandlePaymentNotify 处理支付回调
func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNotifyReq) error {
func (s *payment) HandlePaymentNotify(ctx context.Context, req *dto.PaymentNotifyReq) error {
// 1. 验证回调签名
if !s.verifyNotifySignature(req) {
return errors.New("签名验证失败")
}
// 2. 查询支付记录
paymentRecord, err := s.paymentRecordDao.GetByOrderNo(ctx, req.TenantID, req.OrderNo)
paymentRecord, err := dao.PaymentRecord.GetByOrderNo(ctx, req.TenantID, req.OrderNo)
if err != nil {
return fmt.Errorf("查询支付记录失败: %w", err)
}
@@ -202,7 +184,7 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
}
// 3. 更新支付记录状态
if err := s.paymentRecordDao.UpdateStatus(ctx, paymentRecord.ID.Hex(), req.Status, req.TransactionID, req.TradeNo); err != nil {
if err := dao.PaymentRecord.UpdateStatus(ctx, paymentRecord.ID.Hex(), req.Status, req.TransactionID, req.TradeNo); err != nil {
return fmt.Errorf("更新支付记录失败: %w", err)
}
@@ -215,7 +197,7 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
"payment_channel": req.PayMethod,
}
if err := s.orderDao.MoveOrderToStatus(ctx, entity.OrderStatusPending, entity.OrderStatusPaid, req.TenantID, req.OrderNo, updateData); err != nil {
if err := dao.Order.MoveOrderToStatus(ctx, consts.OrderStatusPending, consts.OrderStatusPaid, req.TenantID, req.OrderNo, updateData); err != nil {
return fmt.Errorf("更新订单状态失败: %w", err)
}
}
@@ -223,34 +205,22 @@ func (s *PaymentService) HandlePaymentNotify(ctx context.Context, req *PaymentNo
return nil
}
// PaymentNotifyReq 支付回调请求
type PaymentNotifyReq struct {
TenantID string `json:"tenant_id"` // 租户ID
OrderNo string `json:"order_no"` // 订单号
PayMethod string `json:"pay_method"` // 支付方式
Status string `json:"status"` // 支付状态
TransactionID string `json:"transaction_id"` // 交易号
TradeNo string `json:"trade_no"` // 交易号
Sign string `json:"sign"` // 签名
}
// verifyNotifySignature 验证回调签名
func (s *PaymentService) verifyNotifySignature(req *PaymentNotifyReq) bool {
func (s *payment) verifyNotifySignature(req *dto.PaymentNotifyReq) bool {
// 这里应该是实际的签名验证逻辑
// 为了演示我们总是返回true
return true
}
// RefundOrder 退款
func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderReq) (*dto.RefundOrderResp, error) {
func (s *payment) RefundOrder(ctx context.Context, req *dto.RefundOrderReq) (*dto.RefundOrderResp, error) {
// 1. 参数验证
if req.TenantID == "" || req.OrderNo == "" || req.RefundAmount <= 0 {
return nil, errors.New("必填参数不能为空")
}
// 2. 查询订单
order, status, err := s.orderDao.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
order, status, err := dao.Order.GetOrderByNo(ctx, req.TenantID, req.OrderNo)
if err != nil {
return nil, fmt.Errorf("获取订单失败: %w", err)
}
@@ -260,7 +230,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
}
// 3. 验证订单状态(只有已支付订单可以退款)
if status != entity.OrderStatusPaid {
if status != consts.OrderStatusPaid {
return nil, fmt.Errorf("订单状态不正确,当前状态: %s", status)
}
@@ -291,7 +261,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
Status: "pending",
}
if err := s.refundRecordDao.Create(ctx, refundRecord); err != nil {
if err := dao.RefundRecord.Create(ctx, refundRecord); err != nil {
return nil, fmt.Errorf("创建退款记录失败: %w", err)
}
@@ -301,7 +271,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
"refund_reason": req.Reason,
}
if err := s.orderDao.MoveOrderToStatus(ctx, entity.OrderStatusPaid, entity.OrderStatusRefunded, req.TenantID, req.OrderNo, updateData); err != nil {
if err := dao.Order.MoveOrderToStatus(ctx, consts.OrderStatusPaid, consts.OrderStatusRefunded, req.TenantID, req.OrderNo, updateData); err != nil {
return nil, fmt.Errorf("更新订单状态失败: %w", err)
}
}
@@ -317,7 +287,7 @@ func (s *PaymentService) RefundOrder(ctx context.Context, req *dto.RefundOrderRe
}
// callThirdPartyRefund 调用第三方退款接口
func (s *PaymentService) callThirdPartyRefund(ctx context.Context, req *dto.RefundOrderReq, order *entity.OrderPaid) (*RefundResponse, error) {
func (s *payment) callThirdPartyRefund(ctx context.Context, req *dto.RefundOrderReq, order *entity.OrderPaid) (*RefundResponse, error) {
// 这里应该是实际的第三方退款接口调用
// 为了演示,我们返回模拟数据
@@ -338,21 +308,21 @@ type RefundResponse struct {
}
// generateRefundNo 生成退款单号
func (s *PaymentService) generateRefundNo(tenantID string) string {
func (s *payment) generateRefundNo(tenantID string) string {
timestamp := time.Now().Format("20060102150405")
random := rand.Intn(10000)
return fmt.Sprintf("R%s%s%04d", tenantID, timestamp, random)
}
// HandleRefundNotify 处理退款回调
func (s *PaymentService) HandleRefundNotify(ctx context.Context, req *RefundNotifyReq) error {
func (s *payment) HandleRefundNotify(ctx context.Context, req *dto.RefundNotifyReq) error {
// 1. 验证回调签名
if !s.verifyRefundNotifySignature(req) {
return errors.New("签名验证失败")
}
// 2. 查询退款记录
refundRecord, err := s.refundRecordDao.GetByRefundNo(ctx, req.TenantID, req.RefundNo)
refundRecord, err := dao.RefundRecord.GetByRefundNo(ctx, req.TenantID, req.RefundNo)
if err != nil {
return fmt.Errorf("查询退款记录失败: %w", err)
}
@@ -362,25 +332,15 @@ func (s *PaymentService) HandleRefundNotify(ctx context.Context, req *RefundNoti
}
// 3. 更新退款记录状态
if err := s.refundRecordDao.UpdateRefundStatus(ctx, refundRecord.ID.Hex(), req.Status, req.RefundID); err != nil {
if err := dao.RefundRecord.UpdateRefundStatus(ctx, refundRecord.ID.Hex(), req.Status, req.RefundID); err != nil {
return fmt.Errorf("更新退款记录失败: %w", err)
}
return nil
}
// RefundNotifyReq 退款回调请求
type RefundNotifyReq struct {
TenantID string `json:"tenant_id"` // 租户ID
RefundNo string `json:"refund_no"` // 退款单号
Status string `json:"status"` // 退款状态
RefundID string `json:"refund_id"` // 退款ID
Sign string `json:"sign"` // 签名
}
// verifyRefundNotifySignature 验证退款回调签名
func (s *PaymentService) verifyRefundNotifySignature(req *RefundNotifyReq) bool {
func (s *payment) verifyRefundNotifySignature(req *dto.RefundNotifyReq) bool {
// 这里应该是实际的签名验证逻辑
// 为了演示我们总是返回true
return true