You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
7.6 KiB
Go

package order
import (
"bytes"
dto "cls/internal/application/payment"
"cls/internal/domain/article"
"cls/internal/domain/column"
"cls/internal/domain/coupon"
"cls/internal/domain/order"
"cls/internal/domain/payment"
"cls/internal/domain/price"
"cls/internal/domain/user"
"cls/internal/infrastructure/payment/wechat_pay"
"cls/pkg/logger"
"errors"
"fmt"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
"time"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
)
// OrderService 订单应用服务
type OrderService struct {
orderRepo order.OrderRepository
repo order.AggregateRepository
articleRepo article.ArticleRepository
columnRepo column.ColumnRepository
priceRepo price.PriceRepository
payService *wechat_pay.PayService
userRepo user.UserRepository
couponRepo coupon.CouponRepository
log logger.Logger
}
// NewOrderService 创建订单应用服务
func NewOrderService(repo order.AggregateRepository, articleRepo article.ArticleRepository,
priceRepo price.PriceRepository, userRepo user.UserRepository,
couponRepo coupon.CouponRepository, payService *wechat_pay.PayService,
orderRepo order.OrderRepository,
columnRepo column.ColumnRepository, log logger.New) *OrderService {
return &OrderService{
repo: repo,
articleRepo: articleRepo,
priceRepo: priceRepo,
columnRepo: columnRepo,
payService: payService,
orderRepo: orderRepo,
userRepo: userRepo,
couponRepo: couponRepo,
log: log("cls:service:order"),
}
}
// CreateOrder 创建订单
func (s *OrderService) CreateOrder(req *CreateOrderRequest, ePhone string) (*jsapi.PrepayWithRequestPaymentResponse, error) {
fmt.Println("=============")
fmt.Println(req)
uInfo, err := s.userRepo.FindByPhone(ePhone)
if err != nil {
s.log.Error(err)
return nil, err
}
if uInfo.Openid == "" {
s.log.Error(fmt.Sprintf("用户【%d】openid为空", req.UserID))
return nil, errors.New("")
}
oInfo, err := s.orderRepo.GetPendingOrder(req.TargetID, req.Type, uInfo.Id)
if err != nil {
s.log.Error(err)
return nil, err
}
if oInfo.ID > 0 {
s.log.Errorf("存在相同订单【%d】【%d】", req.TargetID, req.Type)
return nil, errors.New("存在相同订单")
}
priceInfo, err := s.priceRepo.FindByTargetID(req.TargetID, price.PriceType(req.Type))
if err != nil {
s.log.Error(err)
return nil, err
}
fmt.Println("==============")
fmt.Printf("%+v\n", priceInfo)
fmt.Println("==============")
descripton := &bytes.Buffer{}
descripton.Write([]byte("上海路程-"))
if req.Type == order.OrderTypeArticle {
//购买文章,校验文章
req.Amount = priceInfo.Amount
descripton.Write([]byte("文章消费"))
} else {
//购买专栏,校验专栏
switch req.Duration {
case 1:
priceInfo.Amount = priceInfo.OneMonthPrice
case 3:
priceInfo.Amount = priceInfo.ThreeMonthsPrice
case 6:
priceInfo.Amount = priceInfo.SixMonthsPrice
case 12:
priceInfo.Amount = priceInfo.OneYearPrice
}
cInfo, err := s.columnRepo.FindByID(req.TargetID)
if err != nil {
s.log.Error(err)
return nil, err
}
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}
if req.CouponId != 0 {
fmt.Println("使用优惠券")
//使用优惠券
couponInfo, err = s.couponRepo.GetByID(req.CouponId)
if err != nil {
s.log.Error(err)
return nil, err
}
couponInfo.UserID = uInfo.Id
couponInfo.UsedAt = time.Now()
fmt.Printf("%+v\n", couponInfo)
if couponInfo.CanUse(req.Amount) {
fmt.Println("can use")
req.Amount = priceInfo.GetFinalAmountWitCoupon(couponInfo.Value)
} else {
fmt.Println("cann't use it")
}
couponInfo.Status = coupon.CouponStatusUsed
} else {
fmt.Println("不使用优惠券")
req.Amount = priceInfo.GetFinalAmount()
}
fmt.Printf("%+v\n", req)
if req.Amount <= 0 {
s.log.Error("价格小于0元")
return nil, errors.New("")
}
// 创建订单
o := &order.Order{
OrderNo: s.generateOrderNo(),
UserID: uInfo.Id,
TargetID: req.TargetID,
Coupon: req.CouponId,
Type: req.Type,
Amount: req.Amount,
Duration: req.Duration,
Status: order.OrderStatusPending,
Description: req.Description,
}
// 创建聚合根
aggregate := order.NewOrderAggregate(o)
err = aggregate.CreatePayment(payment.PaymentTypeWechat)
if err != nil {
s.log.Error(err)
return nil, err
}
aggregate.Coupon = couponInfo
resp, err := s.payService.CreatePayment(&wechat_pay.PaymentInfo{
Description: descripton.String(),
Attach: "",
OutTradeNo: o.OrderNo,
AmountTotal: req.Amount,
OpenId: uInfo.Openid,
})
if err != nil {
s.log.Error(err)
return nil, err
}
// 保存聚合根
if err = s.repo.Save(aggregate); err != nil {
s.log.Error(err)
return nil, err
}
return resp, nil
}
func (s *OrderService) CancelOrder(req *CreateOrderRequest, ePhone string) error {
uInfo, err := s.userRepo.FindByPhone(ePhone)
if err != nil {
s.log.Error(err)
return err
}
oInfo, err := s.orderRepo.GetPendingOrder(req.TargetID, req.Type, uInfo.Id)
if err != nil {
s.log.Error(err)
return err
}
if oInfo.ID < 1 {
s.log.Errorf("不存在的产品订购信息[%d][%d]", req.TargetID, req.Type)
return errors.New("")
}
agg, err := s.repo.GetByOrderNo(oInfo.OrderNo)
if err != nil {
s.log.Error(err)
return err
}
err = agg.HandlePaymentFailed("H5端取消支付")
if err != nil {
s.log.Error(err)
return err
}
err = s.repo.PayFailed(agg)
if err != nil {
s.log.Error(err)
}
return err
}
func (s *OrderService) OrderNotify(transaction *payments.Transaction) error {
s.log.Info("订单回调======>")
s.log.Infof("%+v\n", *transaction)
aggregate, err := s.repo.GetByOrderNo(*transaction.OutTradeNo)
if err != nil {
s.log.Error(err)
return err
}
if *transaction.Amount.Total != aggregate.Order.Amount {
err = aggregate.HandlePaymentFailed(fmt.Sprintf("订单金额不匹配 %+v", transaction))
if err != nil {
s.log.Error(err)
return err
}
err = s.repo.PayFailed(aggregate)
if err != nil {
s.log.Error(err)
return err
}
}
if *transaction.TradeState == "SUCCESS" {
err = aggregate.HandlePaymentSuccess(*transaction.TransactionId, fmt.Sprintf("%+v", transaction))
if err != nil {
s.log.Error(err)
return err
}
err = s.repo.PaySuccess(aggregate)
if err != nil {
s.log.Error(err)
return err
}
} else {
err = aggregate.HandlePaymentFailed(fmt.Sprintf("%+v", transaction))
if err != nil {
s.log.Error(err)
return err
}
err = s.repo.PayFailed(aggregate)
if err != nil {
s.log.Error(err)
return err
}
}
return nil
}
// CreatePayment 创建支付订单
func (s *OrderService) CreatePayment(orderNo string, paymentType payment.PaymentType) (*dto.PaymentResponse, error) {
// 获取订单聚合根
aggregate, err := s.repo.GetByOrderNo(orderNo)
if err != nil {
s.log.Error(err)
return nil, err
}
// 创建支付订单
if err := aggregate.CreatePayment(paymentType); err != nil {
return nil, err
}
// 保存聚合根
if err := s.repo.Save(aggregate); err != nil {
s.log.Error(err)
return nil, err
}
return dto.FromEntity(aggregate.Payment), nil
}
// DeleteOrder 删除订单
func (s *OrderService) DeleteOrder(id uint64) error {
if err := s.repo.Delete(id); err != nil {
s.log.Error(err)
return err
}
return nil
}
// generateOrderNo 生成订单号
func (s *OrderService) generateOrderNo() string {
return fmt.Sprintf("LCPAY%d%d", time.Now().UnixNano()/1e6, time.Now().Unix()%1000)
}