Compare commits

..

2 Commits

Author SHA1 Message Date
06cc059998 feat: 修改订单创建逻辑,直接使用Post对象而非PostID
Some checks failed
build quyun / Build (push) Failing after 1m23s
2025-12-20 00:07:56 +08:00
109cd3b52d refactor: 移除wepay依赖,简化订单退款逻辑 2025-12-20 00:00:57 +08:00
5 changed files with 17 additions and 89 deletions

View File

@@ -1,16 +1,11 @@
package admin package admin
import ( import (
"fmt"
"quyun/v2/app/requests" "quyun/v2/app/requests"
"quyun/v2/app/services" "quyun/v2/app/services"
"quyun/v2/database/models" "quyun/v2/database/models"
"quyun/v2/pkg/fields"
"quyun/v2/providers/wepay"
"github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3"
"github.com/pkg/errors"
"go.ipao.vip/gen" "go.ipao.vip/gen"
) )
@@ -20,9 +15,7 @@ type OrderListQuery struct {
} }
// @provider // @provider
type orders struct { type orders struct{}
wepay *wepay.Client
}
// List // List
// //
@@ -62,55 +55,5 @@ func (ctl *orders) List(
// @Router /admin/orders/:id/refund [post] // @Router /admin/orders/:id/refund [post]
// @Bind order path key(id) model(id) // @Bind order path key(id) model(id)
func (ctl *orders) Refund(ctx fiber.Ctx, order *models.Order) error { func (ctl *orders) Refund(ctx fiber.Ctx, order *models.Order) error {
user, err := services.Users.FindByID(ctx, order.UserID) return services.Orders.Refund(ctx, order)
if err != nil {
return err
}
post, err := services.Posts.FindByID(ctx, order.PostID)
if err != nil {
return err
}
if order.PaymentMethod == "balance" {
if err := services.Users.AddBalance(ctx, user.ID, order.Meta.Data().CostBalance); err != nil {
return errors.Wrap(err, "add balance failed")
}
if err := services.Users.RevokeUserPosts(ctx, user.ID, order.PostID); err != nil {
return errors.Wrap(err, "revoke posts failed")
}
order.Status = fields.OrderStatusRefundSuccess
if _, err := order.Update(ctx); err != nil {
return errors.Wrap(err, "update order failed")
}
return nil
}
refundTotal := order.Price*int64(order.Discount)/100 - order.Meta.Data().CostBalance
resp, err := ctl.wepay.Refund(ctx, func(bm *wepay.BodyMap) {
bm.
OutRefundNo(order.OrderNo).
OutTradeNo(order.OrderNo).
TransactionID(order.TransactionID).
CNYRefundAmount(refundTotal, refundTotal).
RefundReason(fmt.Sprintf("%s 退款", post.Title))
})
if err != nil {
return err
}
meta := order.Meta.Data()
meta.RefundResp = resp
order.Meta = meta.JsonType()
order.RefundTransactionID = resp.RefundId
order.Status = fields.OrderStatusRefundProcessing
if _, err := order.Update(ctx); err != nil {
return err
}
return nil
} }

View File

@@ -6,7 +6,6 @@ import (
"quyun/v2/providers/app" "quyun/v2/providers/app"
"quyun/v2/providers/job" "quyun/v2/providers/job"
"quyun/v2/providers/jwt" "quyun/v2/providers/jwt"
"quyun/v2/providers/wepay"
"go.ipao.vip/atom" "go.ipao.vip/atom"
"go.ipao.vip/atom/container" "go.ipao.vip/atom/container"
@@ -37,12 +36,8 @@ func Provide(opts ...opt.Option) error {
}); err != nil { }); err != nil {
return err return err
} }
if err := container.Container.Provide(func( if err := container.Container.Provide(func() (*orders, error) {
wepay *wepay.Client, obj := &orders{}
) (*orders, error) {
obj := &orders{
wepay: wepay,
}
return obj, nil return obj, nil
}); err != nil { }); err != nil {

View File

@@ -14,7 +14,6 @@ import (
"quyun/v2/providers/ali" "quyun/v2/providers/ali"
"quyun/v2/providers/app" "quyun/v2/providers/app"
"quyun/v2/providers/job" "quyun/v2/providers/job"
"quyun/v2/providers/wepay"
"github.com/go-pay/gopay/wechat/v3" "github.com/go-pay/gopay/wechat/v3"
"github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3"
@@ -30,10 +29,9 @@ type ListQuery struct {
// @provider // @provider
type posts struct { type posts struct {
wepay *wepay.Client oss *ali.OSSClient
oss *ali.OSSClient job *job.Job
job *job.Job app *app.Config
app *app.Config
} }
// List posts // List posts
@@ -322,7 +320,7 @@ func (ctl *posts) Buy(ctx fiber.Ctx, post *models.Post, user *models.User) (*wec
} }
// payPrice := post.PayPrice() // payPrice := post.PayPrice()
order, err := services.Orders.CreateFromUserPostID(ctx, user.ID, post.ID) order, err := services.Orders.CreateFromUserPostID(ctx, user.ID, post)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "订单创建失败") return nil, errors.Wrap(err, "订单创建失败")
} }

View File

@@ -5,7 +5,6 @@ import (
"quyun/v2/providers/ali" "quyun/v2/providers/ali"
"quyun/v2/providers/app" "quyun/v2/providers/app"
"quyun/v2/providers/job" "quyun/v2/providers/job"
"quyun/v2/providers/wepay"
"go.ipao.vip/atom" "go.ipao.vip/atom"
"go.ipao.vip/atom/container" "go.ipao.vip/atom/container"
@@ -18,13 +17,11 @@ func Provide(opts ...opt.Option) error {
app *app.Config, app *app.Config,
job *job.Job, job *job.Job,
oss *ali.OSSClient, oss *ali.OSSClient,
wepay *wepay.Client,
) (*posts, error) { ) (*posts, error) {
obj := &posts{ obj := &posts{
app: app, app: app,
job: job, job: job,
oss: oss, oss: oss,
wepay: wepay,
} }
return obj, nil return obj, nil

View File

@@ -77,12 +77,12 @@ func (m *orders) List(
} }
// Refund 订单退款(余额支付走本地退款;微信支付走微信退款并标记为退款处理中)。 // Refund 订单退款(余额支付走本地退款;微信支付走微信退款并标记为退款处理中)。
func (m *orders) Refund(ctx context.Context, id int64) error { func (m *orders) Refund(ctx context.Context, order *models.Order) error {
// 余额支付:这里强调“状态一致性”,必须在一个事务中完成:余额退回 + 撤销购买权益 + 更新订单状态。 // 余额支付:这里强调“状态一致性”,必须在一个事务中完成:余额退回 + 撤销购买权益 + 更新订单状态。
return models.Q.Transaction(func(tx *models.Query) error { return models.Q.Transaction(func(tx *models.Query) error {
order, err := tx.Order.WithContext(ctx).GetByID(id) // 已移除微信退款wepay能力仅支持余额支付订单退款。
if err != nil { if order.PaymentMethod != "balance" {
return errors.Wrap(err, "failed to get order in tx") return errors.New("暂不支持该支付方式退款")
} }
// 退回余额(使用原子自增,避免并发覆盖)。 // 退回余额(使用原子自增,避免并发覆盖)。
@@ -124,18 +124,13 @@ func (m *orders) GetByOrderNO(ctx context.Context, orderNo string) (*models.Orde
return models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.OrderNo.Eq(orderNo)).First() return models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.OrderNo.Eq(orderNo)).First()
} }
func (o *orders) CreateFromUserPostID(ctx context.Context, userId, postId int64) (*models.Order, error) { func (o *orders) CreateFromUserPostID(ctx context.Context, userId int64, post *models.Post) (*models.Order, error) {
post, err := Posts.FindByID(ctx, postId)
if err != nil {
return nil, errors.Wrap(err, "failed to get post")
}
m := &models.Order{} m := &models.Order{}
m.Status = fields.OrderStatusPending m.Status = fields.OrderStatusPending
m.OrderNo = time.Now().Format("20060102150405") m.OrderNo = time.Now().Format("20060102150405")
m.SubOrderNo = m.OrderNo m.SubOrderNo = m.OrderNo
m.UserID = userId m.UserID = userId
m.PostID = postId m.PostID = post.ID
m.Meta = types.NewJSONType(fields.OrderMeta{}) m.Meta = types.NewJSONType(fields.OrderMeta{})
m.Price = post.Price m.Price = post.Price
m.Discount = post.Discount m.Discount = post.Discount