Compare commits
2 Commits
df6a8de61d
...
06cc059998
| Author | SHA1 | Date | |
|---|---|---|---|
| 06cc059998 | |||
| 109cd3b52d |
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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, "订单创建失败")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user