feat(1.0.4):增加订单日志接口

developing
张帅 1 week ago
parent a925ad776d
commit b95732f07d

@ -9,6 +9,7 @@ import (
"cls/internal/domain/order" "cls/internal/domain/order"
"cls/internal/domain/payment" "cls/internal/domain/payment"
"cls/internal/domain/price" "cls/internal/domain/price"
"cls/internal/domain/run_log"
"cls/internal/domain/user" "cls/internal/domain/user"
"cls/internal/infrastructure/payment/wechat_pay" "cls/internal/infrastructure/payment/wechat_pay"
"cls/pkg/logger" "cls/pkg/logger"
@ -27,6 +28,7 @@ type OrderService struct {
articleRepo article.ArticleRepository articleRepo article.ArticleRepository
columnRepo column.ColumnRepository columnRepo column.ColumnRepository
priceRepo price.PriceRepository priceRepo price.PriceRepository
runLog run_log.RunLogRepository
payService *wechat_pay.PayService payService *wechat_pay.PayService
userRepo user.UserRepository userRepo user.UserRepository
couponRepo coupon.CouponRepository couponRepo coupon.CouponRepository
@ -37,7 +39,7 @@ type OrderService struct {
func NewOrderService(repo order.AggregateRepository, articleRepo article.ArticleRepository, func NewOrderService(repo order.AggregateRepository, articleRepo article.ArticleRepository,
priceRepo price.PriceRepository, userRepo user.UserRepository, priceRepo price.PriceRepository, userRepo user.UserRepository,
couponRepo coupon.CouponRepository, payService *wechat_pay.PayService, couponRepo coupon.CouponRepository, payService *wechat_pay.PayService,
orderRepo order.OrderRepository, orderRepo order.OrderRepository, runLog run_log.RunLogRepository,
columnRepo column.ColumnRepository, log logger.New) *OrderService { columnRepo column.ColumnRepository, log logger.New) *OrderService {
return &OrderService{ return &OrderService{
repo: repo, repo: repo,
@ -114,9 +116,6 @@ func (s *OrderService) CreateOrder(req *CreateOrderRequest, ePhone string) (*jsa
descripton.Write([]byte(fmt.Sprintf("订购专栏【%s】%d个月", cInfo.Title, req.Duration))) descripton.Write([]byte(fmt.Sprintf("订购专栏【%s】%d个月", cInfo.Title, req.Duration)))
} }
fmt.Println("==============")
fmt.Printf("%+v\n", req)
fmt.Println("==============")
couponInfo := &coupon.Coupon{ID: req.CouponId} couponInfo := &coupon.Coupon{ID: req.CouponId}
if req.CouponId != 0 { if req.CouponId != 0 {
@ -131,14 +130,13 @@ func (s *OrderService) CreateOrder(req *CreateOrderRequest, ePhone string) (*jsa
couponInfo.UserID = uInfo.Id couponInfo.UserID = uInfo.Id
couponInfo.UsedAt = time.Now() couponInfo.UsedAt = time.Now()
fmt.Printf("%+v\n", couponInfo) fmt.Printf("%+v\n", couponInfo)
if couponInfo.CanUse(req.Amount) { if couponInfo.CanUse(priceInfo.GetFinalAmount()) {
fmt.Println("can use") fmt.Println("can use")
req.Amount = priceInfo.GetFinalAmountWitCoupon(couponInfo.Value) req.Amount = priceInfo.GetFinalAmountWitCoupon(couponInfo.Value)
couponInfo.Status = coupon.CouponStatusUsed
} else { } else {
fmt.Println("cann't use it") fmt.Println("cann't use it")
} }
couponInfo.Status = coupon.CouponStatusUsed
} else { } else {
fmt.Println("不使用优惠券") fmt.Println("不使用优惠券")
req.Amount = priceInfo.GetFinalAmount() req.Amount = priceInfo.GetFinalAmount()
@ -155,38 +153,48 @@ func (s *OrderService) CreateOrder(req *CreateOrderRequest, ePhone string) (*jsa
OrderNo: s.generateOrderNo(), OrderNo: s.generateOrderNo(),
UserID: uInfo.Id, UserID: uInfo.Id,
TargetID: req.TargetID, TargetID: req.TargetID,
Coupon: req.CouponId,
Type: req.Type, Type: req.Type,
Amount: req.Amount, Amount: req.Amount,
Duration: req.Duration, Duration: req.Duration,
Status: order.OrderStatusPending, Status: order.OrderStatusPending,
Description: req.Description, Description: req.Description,
} }
s.runLog.LogOrderInfo(o.OrderNo, fmt.Sprintf("%+v", o))
// 创建聚合根 // 创建聚合根
aggregate := order.NewOrderAggregate(o) aggregate := order.NewOrderAggregate(o)
err = aggregate.CreatePayment(payment.PaymentTypeWechat) err = aggregate.CreatePayment(payment.PaymentTypeWechat)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(o.OrderNo, err.Error(), "创建支付订单")
s.log.Error(err) s.log.Error(err)
return nil, err return nil, err
} }
aggregate.Coupon = couponInfo if couponInfo.Status == coupon.CouponStatusUsed {
aggregate.Coupon = couponInfo
resp, err := s.payService.CreatePayment(&wechat_pay.PaymentInfo{ o.Coupon = req.CouponId
}
pInfo := &wechat_pay.PaymentInfo{
Description: descripton.String(), Description: descripton.String(),
Attach: "", Attach: "",
OutTradeNo: o.OrderNo, OutTradeNo: o.OrderNo,
AmountTotal: req.Amount, AmountTotal: req.Amount,
OpenId: uInfo.Openid, OpenId: uInfo.Openid,
}) }
s.runLog.LogOrderInfo(o.OrderNo, fmt.Sprintf("%+v", pInfo))
resp, err := s.payService.CreatePayment(pInfo)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(o.OrderNo, err.Error(), "创建WX支付订单")
s.log.Error(err) s.log.Error(err)
return nil, err return nil, err
} }
s.runLog.LogOrderInfo(o.OrderNo, fmt.Sprintf("%+v", resp))
// 保存聚合根 // 保存聚合根
if err = s.repo.Save(aggregate); err != nil { if err = s.repo.Save(aggregate); err != nil {
s.runLog.LogOrderInfo(o.OrderNo, err.Error(), "保存订单")
s.log.Error(err) s.log.Error(err)
return nil, err return nil, err
} }
@ -214,18 +222,21 @@ func (s *OrderService) CancelOrder(req *CreateOrderRequest, ePhone string) error
agg, err := s.repo.GetByOrderNo(oInfo.OrderNo) agg, err := s.repo.GetByOrderNo(oInfo.OrderNo)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(oInfo.OrderNo, err.Error(), "GetByOrderNo")
s.log.Error(err) s.log.Error(err)
return err return err
} }
err = agg.HandlePaymentFailed("H5端取消支付") err = agg.HandlePaymentFailed("H5端取消支付")
if err != nil { if err != nil {
s.runLog.LogOrderInfo(oInfo.OrderNo, err.Error(), "HandlePaymentFailed")
s.log.Error(err) s.log.Error(err)
return err return err
} }
err = s.repo.PayFailed(agg) err = s.repo.PayFailed(agg)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(oInfo.OrderNo, err.Error(), "PayFailed")
s.log.Error(err) s.log.Error(err)
} }
@ -233,22 +244,27 @@ func (s *OrderService) CancelOrder(req *CreateOrderRequest, ePhone string) error
} }
func (s *OrderService) OrderNotify(transaction *payments.Transaction) error { func (s *OrderService) OrderNotify(transaction *payments.Transaction) error {
s.log.Info("订单回调======>") s.runLog.LogOrderInfo(*transaction.OutTradeNo, fmt.Sprintf("%+v", *transaction))
s.log.Infof("%+v\n", *transaction)
aggregate, err := s.repo.GetByOrderNo(*transaction.OutTradeNo) aggregate, err := s.repo.GetByOrderNo(*transaction.OutTradeNo)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(*transaction.OutTradeNo, err.Error(), "GetByOrderNo")
s.log.Error(err) s.log.Error(err)
return err return err
} }
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, fmt.Sprintf("%+v", transaction))
if *transaction.Amount.Total != aggregate.Order.Amount { if *transaction.Amount.Total != aggregate.Order.Amount {
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, "订单金额不匹配")
err = aggregate.HandlePaymentFailed(fmt.Sprintf("订单金额不匹配 %+v", transaction)) err = aggregate.HandlePaymentFailed(fmt.Sprintf("订单金额不匹配 %+v", transaction))
if err != nil { if err != nil {
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, err.Error(), "HandlePaymentFailed")
s.log.Error(err) s.log.Error(err)
return err return err
} }
err = s.repo.PayFailed(aggregate) err = s.repo.PayFailed(aggregate)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, err.Error(), "PayFailed")
s.log.Error(err) s.log.Error(err)
return err return err
} }
@ -257,22 +273,26 @@ func (s *OrderService) OrderNotify(transaction *payments.Transaction) error {
if *transaction.TradeState == "SUCCESS" { if *transaction.TradeState == "SUCCESS" {
err = aggregate.HandlePaymentSuccess(*transaction.TransactionId, fmt.Sprintf("%+v", transaction)) err = aggregate.HandlePaymentSuccess(*transaction.TransactionId, fmt.Sprintf("%+v", transaction))
if err != nil { if err != nil {
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, err.Error(), "HandlePaymentSuccess")
s.log.Error(err) s.log.Error(err)
return err return err
} }
err = s.repo.PaySuccess(aggregate) err = s.repo.PaySuccess(aggregate)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, err.Error(), "PaySuccess")
s.log.Error(err) s.log.Error(err)
return err return err
} }
} else { } else {
err = aggregate.HandlePaymentFailed(fmt.Sprintf("%+v", transaction)) err = aggregate.HandlePaymentFailed(fmt.Sprintf("%+v", transaction))
if err != nil { if err != nil {
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, err.Error(), "HandlePaymentFailed")
s.log.Error(err) s.log.Error(err)
return err return err
} }
err = s.repo.PayFailed(aggregate) err = s.repo.PayFailed(aggregate)
if err != nil { if err != nil {
s.runLog.LogOrderInfo(aggregate.Order.OrderNo, err.Error(), "PayFailed")
s.log.Error(err) s.log.Error(err)
return err return err
} }

@ -0,0 +1,56 @@
package order
import (
"cls/internal/domain/coupon"
price2 "cls/internal/domain/price"
"testing"
)
func TestCreateOrder(t *testing.T) {
price := &price2.Price{
ID: 0,
TargetID: 2000798,
Type: 1,
Amount: 11,
OneMonthPrice: 0,
ThreeMonthsPrice: 0,
SixMonthsPrice: 0,
OneYearPrice: 0,
FirstMontDiscount: 0,
Discount: 0.1,
}
c := coupon.Coupon{Status: coupon.CouponStatusNormal, MinAmount: 2, Value: 2}
t.Log(c.CanUse(price.GetFinalAmount()))
//v := price.GetFinalAmount()
//t.Log("0.1", price.GetFinalAmountWitCoupon(1))
t.Log("0.1", price.GetFinalAmount())
price.Discount = 0.2
//t.Log("0.2", price.GetFinalAmountWitCoupon(1))
t.Log("0.2", price.GetFinalAmount())
price.Discount = 0.3
//t.Log("0.3", price.GetFinalAmountWitCoupon(1))
t.Log("0.3", price.GetFinalAmount())
price.Discount = 0.4
t.Log("0.4", price.GetFinalAmountWitCoupon(1))
//t.Log("0.4", price.GetFinalAmount())
price.Discount = 0.5
t.Log("0.5", price.GetFinalAmountWitCoupon(1))
//t.Log("0.5", price.GetFinalAmount())
price.Discount = 0.6
//t.Log("0.6", price.GetFinalAmountWitCoupon(1))
t.Log("0.6", price.GetFinalAmount())
price.Discount = 0.7
//t.Log("0.7", price.GetFinalAmountWitCoupon(1))
t.Log("0.7", price.GetFinalAmount())
price.Discount = 0.8
//t.Log("0.8", price.GetFinalAmountWitCoupon(1))
t.Log("0.8", price.GetFinalAmount())
price.Discount = 0.9
//t.Log("0.9", price.GetFinalAmountWitCoupon(1))
t.Log("0.9", price.GetFinalAmount())
price.Discount = 1
//t.Log("1", price.GetFinalAmountWitCoupon(1))
t.Log("1", price.GetFinalAmount())
}

@ -65,6 +65,7 @@ func (a *OrderAggregate) HandlePaymentSuccess(transactionID string, notifyData s
ContentId: a.Order.TargetID, ContentId: a.Order.TargetID,
ContentType: purchase.ContentType(a.Order.Type), ContentType: purchase.ContentType(a.Order.Type),
Price: float64(a.Order.Amount) / 100, // 转换为元 Price: float64(a.Order.Amount) / 100, // 转换为元
OrderNo: a.Order.OrderNo,
Duration: a.Order.Duration, Duration: a.Order.Duration,
ContentSource: purchase.ContentSourceBuy, ContentSource: purchase.ContentSourceBuy,
ExpiredAt: time.Now().AddDate(0, a.Order.Duration, 0), ExpiredAt: time.Now().AddDate(0, a.Order.Duration, 0),

@ -1,6 +1,7 @@
package price package price
import ( import (
"math"
"time" "time"
) )
@ -62,7 +63,7 @@ func (p *Price) GetFinalAmount() int64 {
// float32 → float64避免精度损失 // float32 → float64避免精度损失
final := float32(p.Amount) * p.Discount final := float32(p.Amount) * p.Discount
return int64(final) return int64(math.Round(float64(final)))
} }
func (p *Price) GetFinalAmountWitCoupon(value int64) int64 { func (p *Price) GetFinalAmountWitCoupon(value int64) int64 {

@ -20,12 +20,13 @@ const (
// Purchase 内容购买记录 // Purchase 内容购买记录
type Purchase struct { type Purchase struct {
Id uint64 `xorm:"pk autoincr 'id'" json:"id"` Id uint64 `xorm:"pk autoincr 'id'" json:"id"`
UserId uint64 `xorm:"notnull 'user_id'" json:"userId"` UserId uint64 `xorm:"notnull 'user_id'" json:"userId"`
ContentId uint64 `xorm:"notnull 'content_id'" json:"contentId"` ContentId uint64 `xorm:"notnull 'content_id'" json:"contentId"`
ContentType ContentType `xorm:"tinyint(1) notnull 'content_type'" ` ContentType ContentType `xorm:"tinyint(1) notnull 'content_type'" `
Price float64 `xorm:"decimal(10,2) notnull 'price'" json:"price"` Price float64 `xorm:"decimal(10,2) notnull 'price'" json:"price"`
Duration int `xorm:"notnull 'duration'" json:"duration"` // 购买时长文章为0表示永久 Duration int `xorm:"notnull 'duration'" json:"duration"` // 购买时长文章为0表示永久
OrderNo string
ExpiredAt time.Time `xorm:"notnull 'expired_at'" json:"expiredAt"` // 过期时间文章为null表示永久 ExpiredAt time.Time `xorm:"notnull 'expired_at'" json:"expiredAt"` // 过期时间文章为null表示永久
ContentSource ContentSource `xorm:"tinyint(1) notnull 'content_source'" ` ContentSource ContentSource `xorm:"tinyint(1) notnull 'content_source'" `
Status int8 `xorm:"tinyint(1) default 1 'status'" json:"status"` Status int8 `xorm:"tinyint(1) default 1 'status'" json:"status"`

@ -0,0 +1,20 @@
package run_log
import "time"
type RunLogType uint8
const (
LogTypeOrder = iota + 1
LogTypePayment
LogTypePurchase
)
type RunLog struct {
Id int64
LogType RunLogType
OrderNo string
Remark string
Info string `xorm:"varchar(5000)"`
Created time.Time `xorm:"created"`
}

@ -0,0 +1,7 @@
package run_log
type RunLogRepository interface {
Log(log *RunLog)
LogOrderInfo(orderNo string, info string, remark ...string)
LogPaymentInfo(orderNo string, info string, remark ...string)
}

@ -55,7 +55,7 @@ func (a AuthRepositoryORM) LoginByPassword(phone, password string) (string, erro
func (a AuthRepositoryORM) LoginByCaptcha(phone, openid string) (string, error) { func (a AuthRepositoryORM) LoginByCaptcha(phone, openid string) (string, error) {
u := &domainUser.User{} u := &domainUser.User{}
has, err := a.engine.Where(builder.Eq{"phone": phone}.And(builder.Eq{"openid": openid})).Get(u) has, err := a.engine.Where(builder.Eq{"phone": phone}).Get(u)
if err != nil { if err != nil {
a.log.Error(err) a.log.Error(err)
return "", err return "", err
@ -72,6 +72,10 @@ func (a AuthRepositoryORM) LoginByCaptcha(phone, openid string) (string, error)
} }
} }
if u.Openid != openid {
return "", errors.New(fmt.Sprintf("openid和手机号不匹配,[%s]-[%s]", phone, openid))
}
if u.Status == 0 { if u.Status == 0 {
return "", errors.New(fmt.Sprintf("用户【%d】禁止登录", u.Id)) return "", errors.New(fmt.Sprintf("用户【%d】禁止登录", u.Id))
} }

@ -0,0 +1,50 @@
package run_log
import (
"cls/internal/domain/run_log"
"cls/pkg/logger"
"cls/pkg/xorm_engine"
"strings"
)
type RunLogRepositoryORM struct {
engine *xorm_engine.Engine
log logger.Logger
}
func NewRunLogRepositoryORM(engine *xorm_engine.Engine, log logger.New) run_log.RunLogRepository {
return &RunLogRepositoryORM{engine, log("cls:persistence:run_log")}
}
var _ run_log.RunLogRepository = (*RunLogRepositoryORM)(nil)
func (r *RunLogRepositoryORM) Log(log *run_log.RunLog) {
_, err := r.engine.Insert(log)
if err != nil {
r.log.Error(err)
}
}
func (r *RunLogRepositoryORM) LogOrderInfo(orderNo string, info string, remark ...string) {
_, err := r.engine.Insert(&run_log.RunLog{
LogType: run_log.LogTypeOrder,
OrderNo: orderNo,
Info: info,
Remark: strings.Join(remark, "|"),
})
if err != nil {
r.log.Error(err)
}
}
func (r *RunLogRepositoryORM) LogPaymentInfo(orderNo string, info string, remark ...string) {
_, err := r.engine.Insert(&run_log.RunLog{
LogType: run_log.LogTypePayment,
OrderNo: orderNo,
Info: info,
Remark: strings.Join(remark, "|"),
})
if err != nil {
r.log.Error(err)
}
}

@ -9,6 +9,7 @@ import (
"cls/internal/domain/payment" "cls/internal/domain/payment"
"cls/internal/domain/price" "cls/internal/domain/price"
"cls/internal/domain/purchase" "cls/internal/domain/purchase"
"cls/internal/domain/run_log"
"cls/internal/domain/user" "cls/internal/domain/user"
"cls/pkg/logger" "cls/pkg/logger"
"cls/pkg/xorm_engine" "cls/pkg/xorm_engine"
@ -49,6 +50,7 @@ func registerModels(engine *xorm_engine.Engine, logger logger.New) {
&order.Order{}, &order.Order{},
&payment.Payment{}, &payment.Payment{},
&coupon.Coupon{}, &coupon.Coupon{},
&run_log.RunLog{},
); err != nil { ); err != nil {
log.Error(err) log.Error(err)
} }

@ -3,6 +3,7 @@ package modules
import ( import (
service "cls/internal/application/order" service "cls/internal/application/order"
repo "cls/internal/infrastructure/persistence/order" repo "cls/internal/infrastructure/persistence/order"
"cls/internal/infrastructure/persistence/run_log"
"cls/internal/interfaces" "cls/internal/interfaces"
"cls/internal/interfaces/order" "cls/internal/interfaces/order"
"go.uber.org/fx" "go.uber.org/fx"
@ -14,6 +15,7 @@ var OrderModule = fx.Module("order",
interfaces.AsHandler(order.NewOrderHandler), interfaces.AsHandler(order.NewOrderHandler),
repo.NewOrderRepositoryORM, repo.NewOrderRepositoryORM,
repo.NewAggregateRepositoryORM, repo.NewAggregateRepositoryORM,
run_log.NewRunLogRepositoryORM,
service.NewOrderService, service.NewOrderService,
), ),
) )

Loading…
Cancel
Save