280 lines
8.4 KiB
Go
280 lines
8.4 KiB
Go
package app
|
||
|
||
import (
|
||
"fmt"
|
||
"git.echol.cn/loser/lckt/model/vip"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"git.echol.cn/loser/lckt/global"
|
||
"git.echol.cn/loser/lckt/model/app"
|
||
"git.echol.cn/loser/lckt/model/app/request"
|
||
"git.echol.cn/loser/lckt/model/user"
|
||
"git.echol.cn/loser/lckt/utils/wechat"
|
||
"github.com/gin-gonic/gin"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
type OrderService struct{}
|
||
|
||
// Pay 发起支付
|
||
func (s *OrderService) Pay(p request.PayReq, ctx *gin.Context) (interface{}, error) {
|
||
order := app.Order{}
|
||
err := global.GVA_DB.Where("id = ? AND order_no = ?", p.OrderId, p.OrderNo).First(&order).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询订单失败", zap.Error(err))
|
||
return "", err
|
||
}
|
||
|
||
if order.Status == 3 {
|
||
global.GVA_LOG.Error("订单已过期", zap.Int64("order_id", int64(order.ID)))
|
||
return "", fmt.Errorf("订单已过期")
|
||
}
|
||
|
||
if p.Mode == "h5" {
|
||
payConf, err := wechat.H5Pay(&order, ctx)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("微信支付订单失败", zap.Error(err))
|
||
return "", err
|
||
}
|
||
return payConf, nil
|
||
} else if p.Mode == "jsapi" {
|
||
payConf, err := wechat.JSAPIPay(&order, ctx)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("微信支付订单失败", zap.Error(err))
|
||
return "", err
|
||
}
|
||
return payConf, nil
|
||
}
|
||
|
||
return "", nil
|
||
}
|
||
|
||
func (s *OrderService) Create(o *app.Order) (*app.Order, error) {
|
||
// 生成订单号
|
||
o.OrderNo = wechat.GenerateOrderNum()
|
||
|
||
// 查询订单商品价格
|
||
price := 0
|
||
switch o.OrderType {
|
||
case 1:
|
||
err := global.GVA_DB.Table("article").Select("price").Where("id = ?", o.ArticleId).Scan(&price).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询商品价格失败", zap.Error(err))
|
||
return nil, err
|
||
}
|
||
case 2:
|
||
err := global.GVA_DB.Table("lckt_vip").Select("price").Where("id = ?", o.VipId).Scan(&price).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询VIP价格失败", zap.Error(err))
|
||
return nil, err
|
||
}
|
||
case 3:
|
||
// 讲师包月
|
||
|
||
//切割TeacherVipId字符串
|
||
ids := strings.Split(o.TeacherVipId, ",")
|
||
// 查询每个服务的价格并累加
|
||
totalPrice := 0
|
||
for _, id := range ids {
|
||
var p int
|
||
err := global.GVA_DB.Table("app_teacher_vip").Select("price").Where("id = ?", id).Scan(&p).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询讲师包月价格失败", zap.Error(err))
|
||
return nil, err
|
||
}
|
||
totalPrice += p
|
||
}
|
||
|
||
price = totalPrice
|
||
}
|
||
|
||
o.Price = int64(price)
|
||
o.Status = 1 // 设置订单状态为未付款
|
||
// 设置openid
|
||
openId := ""
|
||
err := global.GVA_DB.Table("app_user").Where("id = ?", o.UserId).Select("open_id").Scan(&openId).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询用户OpenID失败,请检查微信是否绑定", zap.Error(err))
|
||
return nil, fmt.Errorf("查询用户OpenID失败,请检查微信是否绑定")
|
||
}
|
||
o.OpenId = openId
|
||
|
||
err = global.GVA_DB.Create(&o).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("创建订单失败", zap.Error(err))
|
||
return nil, err
|
||
}
|
||
return o, nil
|
||
}
|
||
|
||
func (s *OrderService) GetOrderDetail(id string) (order app.Order, err error) {
|
||
err = global.GVA_DB.Where("id = ?", id).First(&order).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取订单详情失败", zap.Error(err))
|
||
return app.Order{}, err
|
||
}
|
||
return order, nil
|
||
}
|
||
|
||
func (s *OrderService) BalancePay(p request.BalancePay) error {
|
||
order := app.Order{}
|
||
err := global.GVA_DB.Where("id = ? AND order_no = ?", p.OrderId, p.OrderNo).First(&order).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询订单失败", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
if order.Status != 1 {
|
||
global.GVA_LOG.Error("订单状态错误,无法支付", zap.Int("status", order.Status))
|
||
return err
|
||
}
|
||
// 检查用户余额是否足够
|
||
var user user.User
|
||
err = global.GVA_DB.Where("id = ?", p.UserId).First(&user).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询用户信息失败", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
// 将订单价格从分转换为元(保持精度)
|
||
orderPriceInYuan := float64(order.Price) / 100.0
|
||
|
||
// 检查用户余额是否足够(使用float64进行比较,避免精度丢失)
|
||
if user.Balance < float32(orderPriceInYuan) {
|
||
global.GVA_LOG.Error("用户余额不足",
|
||
zap.Float32("balance", user.Balance),
|
||
zap.Float64("order_price_yuan", orderPriceInYuan),
|
||
zap.Int64("order_price_cent", order.Price))
|
||
return fmt.Errorf("用户余额不足")
|
||
}
|
||
|
||
// 扣除用户余额(保持精度)
|
||
newBalance := user.Balance - float32(orderPriceInYuan)
|
||
err = global.GVA_DB.Model(&user).Where("id = ?", p.UserId).Update("balance", newBalance).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("扣除用户余额失败", zap.Error(err))
|
||
return err
|
||
}
|
||
// 更新订单状态为已付款
|
||
order.Status = 2
|
||
err = global.GVA_DB.Model(&order).Where("id = ?", order.ID).Update("status", 2).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("更新订单状态失败", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
// 全站Vip
|
||
if order.OrderType == 2 {
|
||
// 更新用户的会员状态
|
||
user.IsVip = 1
|
||
// 查询用户购买的会员信息
|
||
vipInfo := vip.Vip{}
|
||
err = global.GVA_DB.Model(&vip.Vip{}).Where("id = ?", order.VipId).First(&vipInfo).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("查询会员信息失败", zap.Error(err))
|
||
return nil
|
||
}
|
||
// 计算会员的过期时间
|
||
if user.VipExpireTime != "" {
|
||
expireTime, _ := time.Parse("2006-01-02", user.VipExpireTime)
|
||
if expireTime.After(time.Now()) {
|
||
// 如果会员未过期,则在原有的基础上增加时间
|
||
user.VipExpireTime = expireTime.AddDate(0, 0, int(vipInfo.Expiration)).Format("2006-01-02")
|
||
} else {
|
||
// 如果会员已过期,则从当前时间开始计算
|
||
user.VipExpireTime = time.Now().AddDate(0, 0, int(vipInfo.Expiration)).Format("2006-01-02")
|
||
}
|
||
} else {
|
||
// 如果没有会员时间,则从当前时间开始计算
|
||
user.VipExpireTime = time.Now().AddDate(0, 0, int(vipInfo.Expiration)).Format("2006-01-02")
|
||
}
|
||
err = global.GVA_DB.Save(&user).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("更新用户会员状态失败", zap.Error(err))
|
||
return nil
|
||
}
|
||
}
|
||
// 讲师包月
|
||
if order.OrderType == 3 {
|
||
// 逗号分割字符串
|
||
ids := strings.Split(order.TeacherVipId, ",")
|
||
for _, id := range ids {
|
||
teacherVip := app.UserTeacherVip{}
|
||
teacherVip.TeacherId = uint(order.TeacherId)
|
||
// 将id转为uint
|
||
teacherVipId, _ := strconv.ParseUint(id, 10, 64)
|
||
teacherVip.TeacherVipId = uint(teacherVipId)
|
||
teacherVip.UserId = uint(order.UserId)
|
||
teacherVip.ExpireAt = time.Now().AddDate(0, 1, 0).Format("2006-01-02") // 会员有效期一个月
|
||
teacherVip.IsExpire = 1 // 设置为未过期
|
||
err = global.GVA_DB.Create(&teacherVip).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("购买讲师会员回调处理失败:", zap.Error(err))
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
global.GVA_LOG.Info("余额支付成功", zap.Int64("user_id", int64(p.UserId)), zap.String("order_no", order.OrderNo))
|
||
return nil
|
||
}
|
||
|
||
// AppGetOrderList APP端获取订单列表
|
||
func (s *OrderService) AppGetOrderList(p request.GetOrderList, id uint) (orders []app.Order, total int64, err error) {
|
||
limit := p.PageSize
|
||
offset := p.PageSize * (p.Page - 1)
|
||
|
||
db := global.GVA_DB.Model(&app.Order{}).Where("user_id = ?", id)
|
||
if p.Keyword != "" {
|
||
db = db.Where("title LIKE ? ", "%"+p.Keyword+"%")
|
||
}
|
||
if p.Status != 0 {
|
||
db = db.Where("status = ?", p.Status)
|
||
}
|
||
|
||
err = db.Count(&total).Error
|
||
err = db.Limit(limit).Offset(offset).Order("created_at desc").Find(&orders).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取订单列表失败", zap.Error(err))
|
||
return nil, 0, err
|
||
}
|
||
return
|
||
}
|
||
|
||
// GetOrderList APP端获取订单列表
|
||
func (s *OrderService) GetOrderList(p request.GetOrderList) (orders []app.Order, total int64, err error) {
|
||
limit := p.PageSize
|
||
offset := p.PageSize * (p.Page - 1)
|
||
|
||
db := global.GVA_DB.Model(&app.Order{})
|
||
if p.Title != "" {
|
||
db = db.Where("title LIKE ? ", "%"+p.Title+"%")
|
||
}
|
||
if p.Status != 0 {
|
||
db = db.Where("status = ?", p.Status)
|
||
}
|
||
if p.PayType != 0 {
|
||
db = db.Where("pay_type = ?", p.PayType)
|
||
}
|
||
if p.OrderType != 0 {
|
||
db = db.Where("order_type = ?", p.OrderType)
|
||
}
|
||
|
||
if p.StartTime != "" && p.EndTime != "" {
|
||
db = db.Where("created_at BETWEEN ? AND ?", p.StartTime, p.EndTime)
|
||
}
|
||
if p.Name != "" {
|
||
db = db.Where("name LIKE ? ", "%"+p.Name+"%")
|
||
}
|
||
|
||
err = db.Count(&total).Error
|
||
err = db.Limit(limit).Offset(offset).Order("created_at desc").Find(&orders).Error
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取订单列表失败", zap.Error(err))
|
||
return nil, 0, err
|
||
}
|
||
return
|
||
}
|