Files
nl-video-api/internal/service/payment_order.go
2025-08-03 00:11:15 +08:00

813 lines
21 KiB
Go
Raw Permalink 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 service
import (
"context"
"fmt"
"time"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"nl-video-api/internal/dao"
"nl-video-api/internal/model/entity"
"nl-video-api/utility/response"
)
// PaymentOrderService 支付订单服务
type PaymentOrderService struct{}
// NewPaymentOrderService 创建支付订单服务实例
func NewPaymentOrderService() *PaymentOrderService {
return &PaymentOrderService{}
}
// Create 创建支付订单
func (s *PaymentOrderService) Create(r *ghttp.Request) {
// 获取请求参数
vipLevelId := r.Get("vip_level_id").Uint()
paymentMethod := r.Get("payment_method").String()
amount := r.Get("amount").Float64()
// 参数验证
if vipLevelId == 0 {
response.Error(r, response.CodeInvalidParam, "VIP等级ID不能为空")
return
}
if paymentMethod == "" {
response.Error(r, response.CodeInvalidParam, "支付方式不能为空")
return
}
if amount <= 0 {
response.Error(r, response.CodeInvalidParam, "支付金额必须大于0")
return
}
// 获取当前用户ID临时设置
userId := uint(1)
// 生成订单号
orderNo := "PAY" + gtime.Now().Format("YmdHis") + g.NewVar(userId).String()
// 创建支付订单
data := &entity.PaymentOrder{
OrderNo: orderNo,
UserId: int(userId),
VipLevelId: int(vipLevelId),
Amount: amount,
PaymentMethod: paymentMethod,
PaymentStatus: 0, // 待支付
ExpireTime: gtime.Now().Add(time.Hour * 24), // 24小时后过期
CreatedAt: gtime.Now(),
UpdatedAt: gtime.Now(),
}
id, err := dao.PaymentOrder.Ctx(r.Context()).Data(data).InsertAndGetId()
if err != nil {
response.Error(r, response.CodeInternalError, "创建支付订单失败")
return
}
response.Success(r, g.Map{
"id": uint(id),
"order_no": orderNo,
})
}
// GetList 获取支付订单列表
func (s *PaymentOrderService) GetList(r *ghttp.Request) {
// 获取请求参数
page := r.Get("page", 1).Int()
size := r.Get("size", 10).Int()
status := r.Get("status", -1).Int()
// 获取当前用户ID临时设置
userId := uint(1)
// 构建查询条件
query := dao.PaymentOrder.Ctx(r.Context()).Where("user_id", userId)
// 状态筛选
if status >= 0 {
query = query.Where("payment_status", status)
}
// 获取总数
total, err := query.Count()
if err != nil {
response.Error(r, response.CodeInternalError, "获取订单总数失败")
return
}
// 获取列表数据
var orders []entity.PaymentOrder
err = query.Order("created_at DESC").
Limit((page-1)*size, size).
Scan(&orders)
if err != nil {
response.Error(r, response.CodeInternalError, "获取订单列表失败")
return
}
response.Success(r, g.Map{
"list": orders,
"total": total,
"page": page,
"size": size,
})
}
// GetDetail 获取支付订单详情
func (s *PaymentOrderService) GetDetail(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
// 参数验证
if id == 0 {
response.Error(r, response.CodeInvalidParam, "订单ID不能为空")
return
}
// 获取当前用户ID临时设置
userId := uint(1)
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(r.Context()).Where("id", id).Where("user_id", userId).Scan(&order)
if err != nil {
response.Error(r, response.CodeInternalError, "获取订单信息失败")
return
}
if order.Id == 0 {
response.Error(r, response.CodeNotFound, "订单不存在")
return
}
response.Success(r, order)
}
// Pay 支付订单
func (s *PaymentOrderService) Pay(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
// 参数验证
if id == 0 {
response.Error(r, response.CodeInvalidParam, "订单ID不能为空")
return
}
// 获取当前用户ID临时设置
userId := uint(1)
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(r.Context()).Where("id", id).Where("user_id", userId).Scan(&order)
if err != nil {
response.Error(r, response.CodeInternalError, "获取订单信息失败")
return
}
if order.Id == 0 {
response.Error(r, response.CodeNotFound, "订单不存在")
return
}
// 检查订单状态
if order.PaymentStatus != 0 {
response.Error(r, response.CodeInvalidParam, "订单状态不正确")
return
}
// 更新订单状态为已支付
_, err = dao.PaymentOrder.Ctx(r.Context()).Where("id", id).Data(g.Map{
"payment_status": 1,
"payment_time": gtime.Now(),
"updated_at": gtime.Now(),
}).Update()
if err != nil {
response.Error(r, response.CodeInternalError, "更新订单状态失败")
return
}
response.Success(r, "支付成功")
}
// Cancel 取消订单
func (s *PaymentOrderService) Cancel(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
// 参数验证
if id == 0 {
response.Error(r, response.CodeInvalidParam, "订单ID不能为空")
return
}
// 获取当前用户ID临时设置
userId := uint(1)
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(r.Context()).Where("id", id).Where("user_id", userId).Scan(&order)
if err != nil {
response.Error(r, response.CodeInternalError, "获取订单信息失败")
return
}
if order.Id == 0 {
response.Error(r, response.CodeNotFound, "订单不存在")
return
}
// 检查订单状态
if order.PaymentStatus != 0 {
response.Error(r, response.CodeInvalidParam, "只能取消待支付的订单")
return
}
// 更新订单状态为已取消
_, err = dao.PaymentOrder.Ctx(r.Context()).Where("id", id).Data(g.Map{
"payment_status": 2,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
response.Error(r, response.CodeInternalError, "取消订单失败")
return
}
response.Success(r, "取消成功")
}
// 定义请求和响应结构体
type PaymentOrderCreateReq struct {
VipLevelId uint `json:"vip_level_id"`
PaymentMethod string `json:"payment_method"`
Amount float64 `json:"amount"`
}
type PaymentOrderCreateRes struct {
OrderNo string `json:"order_no"`
Amount float64 `json:"amount"`
}
type PaymentOrderListReq struct {
Page int `json:"page"`
Size int `json:"size"`
PaymentStatus int `json:"payment_status"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
UserId uint `json:"user_id"`
}
type PaymentOrderListRes struct {
List []PaymentOrderItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
type PaymentOrderItem struct {
Id uint `json:"id"`
OrderNo string `json:"order_no"`
UserId uint `json:"user_id"`
Username string `json:"username"`
VipLevelId uint `json:"vip_level_id"`
VipLevelName string `json:"vip_level_name"`
Amount float64 `json:"amount"`
PaymentMethod string `json:"payment_method"`
PaymentStatus int `json:"payment_status"`
PaymentTime int64 `json:"payment_time"`
ExpireTime int64 `json:"expire_time"`
CreatedAt int64 `json:"created_at"`
}
type PaymentOrderDetailReq struct {
Id uint `json:"id"`
}
type PaymentOrderDetailRes struct {
Order PaymentOrderDetail `json:"order"`
}
type PaymentOrderDetail struct {
Id uint `json:"id"`
OrderNo string `json:"order_no"`
UserId uint `json:"user_id"`
Username string `json:"username"`
VipLevelId uint `json:"vip_level_id"`
VipLevelName string `json:"vip_level_name"`
Amount float64 `json:"amount"`
PaymentMethod string `json:"payment_method"`
PaymentStatus int `json:"payment_status"`
PaymentTime int64 `json:"payment_time"`
ExpireTime int64 `json:"expire_time"`
Remark string `json:"remark"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
type PaymentOrderPayReq struct {
OrderNo string `json:"order_no"`
PaymentMethod string `json:"payment_method"`
}
type PaymentOrderCancelReq struct {
Id uint `json:"id"`
}
type PaymentOrderRefundReq struct {
Id uint `json:"id"`
Reason string `json:"reason"`
}
// UserCreate 用户创建支付订单
func (s *PaymentOrderService) UserCreate(r *ghttp.Request) {
// 获取请求参数
vipLevelId := r.Get("vip_level_id").Uint()
paymentMethod := r.Get("payment_method").String()
amount := r.Get("amount").Float64()
if vipLevelId == 0 {
response.Error(r, response.CodeInvalidParam, "VIP等级ID不能为空")
return
}
if paymentMethod == "" {
response.Error(r, response.CodeInvalidParam, "支付方式不能为空")
return
}
if amount <= 0 {
response.Error(r, response.CodeInvalidParam, "支付金额必须大于0")
return
}
// 获取当前用户ID
userId := uint(1) // 临时设置实际应该从JWT中获取
if userId == 0 {
response.Error(r, response.CodeUnauthorized, "用户未登录")
return
}
// 生成订单号
orderNo := fmt.Sprintf("PAY%d%d", time.Now().Unix(), userId)
// 创建订单
data := &entity.PaymentOrder{
OrderNo: orderNo,
UserId: int(userId),
VipLevelId: int(vipLevelId),
Amount: amount,
PaymentMethod: paymentMethod,
PaymentStatus: 0, // 待支付
ExpireTime: gtime.NewFromTime(time.Now().Add(30 * time.Minute)), // 30分钟后过期
CreatedAt: gtime.Now(),
UpdatedAt: gtime.Now(),
}
id, err := dao.PaymentOrder.Ctx(r.Context()).Data(data).InsertAndGetId()
if err != nil {
response.Error(r, response.CodeInternalError, "创建订单失败")
return
}
response.Success(r, g.Map{
"id": uint(id),
"order_no": orderNo,
"amount": amount,
})
}
// UserList 用户获取支付订单列表
func (s *PaymentOrderService) UserList(r *ghttp.Request) {
// 获取请求参数
page := r.Get("page", 1).Int()
size := r.Get("size", 10).Int()
paymentStatus := r.Get("payment_status", -1).Int()
if page <= 0 {
page = 1
}
if size <= 0 {
size = 10
}
// 获取当前用户ID
userId := uint(1) // 临时设置实际应该从JWT中获取
if userId == 0 {
response.Error(r, response.CodeUnauthorized, "用户未登录")
return
}
// 构建查询条件
query := dao.PaymentOrder.Ctx(r.Context()).Where("user_id", userId)
// 支付状态筛选
if paymentStatus >= 0 {
query = query.Where("payment_status", paymentStatus)
}
// 获取总数
total, err := query.Count()
if err != nil {
response.Error(r, response.CodeInternalError, "获取订单总数失败")
return
}
// 获取列表数据
var orders []entity.PaymentOrder
err = query.Order("id DESC").
Limit((page-1)*size, size).
Scan(&orders)
if err != nil {
response.Error(r, response.CodeInternalError, "获取订单列表失败")
return
}
// 转换为响应格式
list := make([]PaymentOrderItem, 0, len(orders))
for _, order := range orders {
var paymentTime int64
if order.PaymentTime != nil {
paymentTime = order.PaymentTime.Unix()
}
list = append(list, PaymentOrderItem{
Id: order.Id,
OrderNo: order.OrderNo,
UserId: uint(order.UserId),
Username: "", // 用户自己的订单,不需要显示用户名
VipLevelId: uint(order.VipLevelId),
VipLevelName: "", // 可以后续关联查询
Amount: order.Amount,
PaymentMethod: order.PaymentMethod,
PaymentStatus: order.PaymentStatus,
PaymentTime: paymentTime,
ExpireTime: order.ExpireTime.Unix(),
CreatedAt: order.CreatedAt.Unix(),
})
}
response.Success(r, g.Map{
"list": list,
"total": total,
"page": page,
"size": size,
})
}
// UserDetail 用户获取支付订单详情
func (s *PaymentOrderService) UserDetail(ctx context.Context, req *PaymentOrderDetailReq) (*PaymentOrderDetailRes, error) {
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(ctx).Where("id", req.Id).Scan(&order)
if err != nil {
return nil, gerror.New("获取订单详情失败")
}
if order.Id == 0 {
return nil, gerror.New("订单不存在")
}
// 获取用户信息
var user entity.NlUser
g.DB().Model("nl_user").Where("id", order.UserId).Fields("username").Scan(&user)
var paymentTime int64
if order.PaymentTime != nil {
paymentTime = order.PaymentTime.Unix()
}
return &PaymentOrderDetailRes{
Order: PaymentOrderDetail{
Id: order.Id,
OrderNo: order.OrderNo,
UserId: uint(order.UserId),
Username: user.Username,
VipLevelId: uint(order.VipLevelId),
VipLevelName: "", // 可以后续关联查询
Amount: order.Amount,
PaymentMethod: order.PaymentMethod,
PaymentStatus: order.PaymentStatus,
PaymentTime: paymentTime,
ExpireTime: order.ExpireTime.Unix(),
Remark: order.Remark,
CreatedAt: order.CreatedAt.Unix(),
UpdatedAt: order.UpdatedAt.Unix(),
},
}, nil
}
// UserPay 用户支付订单
func (s *PaymentOrderService) UserPay(ctx context.Context, req *PaymentOrderPayReq) error {
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(ctx).Where("order_no", req.OrderNo).Scan(&order)
if err != nil {
return gerror.New("获取订单信息失败")
}
if order.Id == 0 {
return gerror.New("订单不存在")
}
// 检查订单状态
if order.PaymentStatus != 0 {
return gerror.New("订单状态不正确")
}
// 检查订单是否过期
if order.ExpireTime.Before(gtime.Now()) {
return gerror.New("订单已过期")
}
// 这里应该调用第三方支付接口
// 模拟支付成功
// 更新订单状态
_, err = dao.PaymentOrder.Ctx(ctx).Where("id", order.Id).Data(g.Map{
"payment_status": 1, // 已支付
"payment_method": req.PaymentMethod,
"payment_time": gtime.Now(),
"updated_at": gtime.Now(),
}).Update()
if err != nil {
return gerror.New("更新订单状态失败")
}
return nil
}
// UserCancel 用户取消订单
func (s *PaymentOrderService) UserCancel(ctx context.Context, req *PaymentOrderCancelReq) error {
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(ctx).Where("id", req.Id).Scan(&order)
if err != nil {
return gerror.New("获取订单信息失败")
}
if order.Id == 0 {
return gerror.New("订单不存在")
}
// 检查订单状态
if order.PaymentStatus != 0 {
return gerror.New("只能取消待支付的订单")
}
// 更新订单状态
_, err = dao.PaymentOrder.Ctx(ctx).Where("id", req.Id).Data(g.Map{
"payment_status": 2, // 已取消
"updated_at": gtime.Now(),
}).Update()
if err != nil {
return gerror.New("取消订单失败")
}
return nil
}
// AdminList 管理员获取支付订单列表
func (s *PaymentOrderService) AdminList(ctx context.Context, req *PaymentOrderListReq) (*PaymentOrderListRes, error) {
// 设置默认值
if req.Page <= 0 {
req.Page = 1
}
if req.Size <= 0 {
req.Size = 10
}
// 构建查询条件
query := dao.PaymentOrder.Ctx(ctx)
// 支付状态筛选
if req.PaymentStatus >= 0 {
query = query.Where("payment_status", req.PaymentStatus)
}
// 用户筛选
if req.UserId > 0 {
query = query.Where("user_id", req.UserId)
}
// 日期范围筛选
if req.StartDate != "" {
query = query.Where("created_at >= ?", req.StartDate+" 00:00:00")
}
if req.EndDate != "" {
query = query.Where("created_at <= ?", req.EndDate+" 23:59:59")
}
// 获取总数
total, err := query.Count()
if err != nil {
return nil, gerror.New("获取订单总数失败")
}
// 获取列表数据
var orders []entity.PaymentOrder
err = query.Order("id DESC").
Limit((req.Page-1)*req.Size, req.Size).
Scan(&orders)
if err != nil {
return nil, gerror.New("获取订单列表失败")
}
// 获取用户信息
userIds := make([]int, 0, len(orders))
for _, order := range orders {
userIds = append(userIds, order.UserId)
}
userMap := make(map[int]string)
if len(userIds) > 0 {
var users []entity.NlUser
g.DB().Model("nl_user").WhereIn("id", userIds).Fields("id, username").Scan(&users)
for _, user := range users {
userMap[int(user.Id)] = user.Username
}
}
// 转换为响应格式
list := make([]PaymentOrderItem, 0, len(orders))
for _, order := range orders {
username := userMap[order.UserId]
var paymentTime int64
if order.PaymentTime != nil {
paymentTime = order.PaymentTime.Unix()
}
list = append(list, PaymentOrderItem{
Id: order.Id,
OrderNo: order.OrderNo,
UserId: uint(order.UserId),
Username: username,
VipLevelId: uint(order.VipLevelId),
VipLevelName: "", // 可以后续关联查询
Amount: order.Amount,
PaymentMethod: order.PaymentMethod,
PaymentStatus: order.PaymentStatus,
PaymentTime: paymentTime,
ExpireTime: order.ExpireTime.Unix(),
CreatedAt: order.CreatedAt.Unix(),
})
}
return &PaymentOrderListRes{
List: list,
Total: total,
Page: req.Page,
Size: req.Size,
}, nil
}
// AdminDetail 管理员获取支付订单详情
func (s *PaymentOrderService) AdminDetail(ctx context.Context, req *PaymentOrderDetailReq) (*PaymentOrderDetailRes, error) {
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(ctx).Where("id", req.Id).Scan(&order)
if err != nil {
return nil, gerror.New("获取订单详情失败")
}
if order.Id == 0 {
return nil, gerror.New("订单不存在")
}
// 获取用户信息
var user entity.NlUser
g.DB().Model("nl_user").Where("id", order.UserId).Fields("username").Scan(&user)
var paymentTime int64
if order.PaymentTime != nil {
paymentTime = order.PaymentTime.Unix()
}
return &PaymentOrderDetailRes{
Order: PaymentOrderDetail{
Id: order.Id,
OrderNo: order.OrderNo,
UserId: uint(order.UserId),
Username: user.Username,
VipLevelId: uint(order.VipLevelId),
VipLevelName: "", // 可以后续关联查询
Amount: order.Amount,
PaymentMethod: order.PaymentMethod,
PaymentStatus: order.PaymentStatus,
PaymentTime: paymentTime,
ExpireTime: order.ExpireTime.Unix(),
Remark: order.Remark,
CreatedAt: order.CreatedAt.Unix(),
UpdatedAt: order.UpdatedAt.Unix(),
},
}, nil
}
// AdminRefund 管理员退款订单
func (s *PaymentOrderService) AdminRefund(ctx context.Context, req *PaymentOrderRefundReq) error {
// 获取订单信息
var order entity.PaymentOrder
err := dao.PaymentOrder.Ctx(ctx).Where("id", req.Id).Scan(&order)
if err != nil {
return gerror.New("获取订单信息失败")
}
if order.Id == 0 {
return gerror.New("订单不存在")
}
// 检查订单状态
if order.PaymentStatus != 1 {
return gerror.New("只能退款已支付的订单")
}
// 这里应该调用第三方支付接口进行退款
// 模拟退款成功
// 更新订单状态
_, err = dao.PaymentOrder.Ctx(ctx).Where("id", req.Id).Data(g.Map{
"payment_status": 3, // 已退款
"remark": req.Reason,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
return gerror.New("更新订单状态失败")
}
return nil
}
// GetStatistics 获取支付统计
func (s *PaymentOrderService) GetStatistics(ctx context.Context, startDate, endDate string) (g.Map, error) {
// 构建查询条件
query := dao.PaymentOrder.Ctx(ctx)
if startDate != "" {
query = query.Where("created_at >= ?", startDate+" 00:00:00")
}
if endDate != "" {
query = query.Where("created_at <= ?", endDate+" 23:59:59")
}
// 获取基础统计
var stats g.Map
query.Fields("COUNT(*) as total_orders, COALESCE(SUM(CASE WHEN payment_status = 1 THEN amount ELSE 0 END), 0) as total_amount, COUNT(CASE WHEN payment_status = 1 THEN 1 END) as paid_orders").
Scan(&stats)
// 获取状态统计
var statusStats []g.Map
dao.PaymentOrder.Ctx(ctx).Fields("payment_status, COUNT(*) as count").
Group("payment_status").Scan(&statusStats)
return g.Map{
"total_orders": gconv.Int(stats["total_orders"]),
"total_amount": gconv.Float64(stats["total_amount"]),
"paid_orders": gconv.Int(stats["paid_orders"]),
"status_stats": statusStats,
}, nil
}
// AdminGetList 管理员获取支付订单列表HTTP接口
func (s *PaymentOrderService) AdminGetList(r *ghttp.Request) {
// 获取请求参数
page := r.Get("page", 1).Int()
size := r.Get("size", 10).Int()
paymentStatus := r.Get("payment_status", -1).Int()
userId := r.Get("user_id", 0).Uint()
startDate := r.Get("start_date").String()
endDate := r.Get("end_date").String()
req := &PaymentOrderListReq{
Page: page,
Size: size,
PaymentStatus: paymentStatus,
UserId: userId,
StartDate: startDate,
EndDate: endDate,
}
res, err := s.AdminList(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// AdminGetDetail 管理员获取支付订单详情HTTP接口
func (s *PaymentOrderService) AdminGetDetail(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
if id == 0 {
response.Error(r, response.CodeInvalidParam, "订单ID不能为空")
return
}
req := &PaymentOrderDetailReq{
Id: id,
}
res, err := s.AdminDetail(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}