完善套餐与账单接口 & 完善支付数据保存,记录实付价格并关联优惠券

This commit is contained in:
2026-03-26 14:39:19 +08:00
parent 5ffa151f58
commit 75ad12efb3
23 changed files with 706 additions and 613 deletions

View File

@@ -1,10 +1,8 @@
package services
import (
"encoding/json"
"fmt"
"platform/web/core"
g "platform/web/globals"
m "platform/web/models"
q "platform/web/queries"
@@ -15,48 +13,29 @@ var User = &userService{}
type userService struct{}
func (s *userService) UpdateBalanceByTrade(uid int32, info *RechargeProductInfo, trade *m.Trade) (err error) {
err = g.Redsync.WithLock(userBalanceKey(uid), func() error {
return q.Q.Transaction(func(q *q.Query) error {
err = updateBalance(q, uid, info)
if err != nil {
return err
}
// 生成账单
subject := info.GetSubject()
amount := info.GetAmount()
err = q.Bill.Create(newForRecharge(uid, Bill.GenNo(), subject, amount, trade))
if err != nil {
return core.NewServErr("生成账单失败", err)
}
return nil
})
})
if err != nil {
return core.NewServErr("更新用户余额失败")
}
return nil
}
func updateBalance(q *q.Query, uid int32, info *RechargeProductInfo) error {
func (s *userService) Get(q *q.Query, uid int32) (*m.User, error) {
user, err := q.User.
Where(q.User.ID.Eq(uid)).Take()
if err != nil {
return core.NewServErr("查询用户失败", err)
return nil, core.NewServErr("查询用户失败", err)
}
return user, nil
}
amount := info.GetAmount()
func (s *userService) UpdateBalance(q *q.Query, user *m.User, amount decimal.Decimal) error {
balance := user.Balance.Add(amount)
if balance.IsNegative() {
return core.NewServErr("用户余额不足")
}
_, err = q.User.
Where(q.User.ID.Eq(user.ID)).
UpdateSimple(q.User.Balance.Value(balance))
_, err := q.User.
Where(
q.User.ID.Eq(user.ID),
q.User.Balance.Eq(user.Balance),
).
UpdateSimple(
q.User.Balance.Value(balance),
)
if err != nil {
return core.NewServErr("更新用户余额失败", err)
}
@@ -68,40 +47,16 @@ func userBalanceKey(uid int32) string {
return fmt.Sprintf("user:%d:balance", uid)
}
type RechargeProductInfo struct {
type UpdateBalanceData struct {
Amount int `json:"amount"`
}
func (r *RechargeProductInfo) GetType() m.TradeType {
return m.TradeTypeRecharge
}
func (r *RechargeProductInfo) GetSubject() string {
return fmt.Sprintf("账户充值 - %s元", r.GetAmount().StringFixed(2))
}
func (r *RechargeProductInfo) GetAmount() decimal.Decimal {
return decimal.NewFromInt(int64(r.Amount)).Div(decimal.NewFromInt(100))
}
func (r *RechargeProductInfo) Serialize() (string, error) {
bytes, err := json.Marshal(r)
return string(bytes), err
}
func (r *RechargeProductInfo) Deserialize(str string) error {
return json.Unmarshal([]byte(str), r)
}
type UserOnTradeComplete struct{}
func (u UserOnTradeComplete) Check(t m.TradeType) (ProductInfo, bool) {
if t == m.TradeTypeRecharge {
return &RechargeProductInfo{}, true
}
return nil, false
}
func (u UserOnTradeComplete) OnTradeComplete(info ProductInfo, trade *m.Trade) error {
return User.UpdateBalanceByTrade(trade.UserID, info.(*RechargeProductInfo), trade)
func (c *UpdateBalanceData) TradeDetail() (*TradeDetail, error) {
amount := decimal.NewFromInt(int64(c.Amount)).Div(decimal.NewFromInt(100))
return &TradeDetail{
m.TradeTypeRecharge,
fmt.Sprintf("账户充值 - %s元", amount.StringFixed(2)),
amount, amount,
nil, c,
}, nil
}