Files
lckt-server/service/app/order.go
2025-07-31 02:40:37 +08:00

168 lines
5.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package app
import (
"fmt"
"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
if o.OrderType == 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
}
} else {
err := global.GVA_DB.Table("lckt_vip").Select("price").Where("id = ?", o.ArticleId).Scan(&price).Error
if err != nil {
global.GVA_LOG.Error("查询VIP价格失败", zap.Error(err))
return nil, err
}
}
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).Select("id,balance").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
}
global.GVA_LOG.Info("余额支付成功", zap.Int64("user_id", int64(p.UserId)), zap.String("order_no", order.OrderNo))
return nil
}
func (s *OrderService) GetOrderList(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
}