重构交易处理逻辑,合并充值与购买流程,优化交易状态管理;更新相关数据结构和接口
This commit is contained in:
@@ -1,54 +1,107 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/shopspring/decimal"
|
||||
"platform/web/core"
|
||||
bill2 "platform/web/domains/bill"
|
||||
trade2 "platform/web/domains/trade"
|
||||
g "platform/web/globals"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
"time"
|
||||
)
|
||||
|
||||
var User = &userService{}
|
||||
|
||||
type userService struct{}
|
||||
|
||||
func (s *userService) RechargeConfirm(tradeNo string, verified *TradeSuccessResult) error {
|
||||
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 := q.Q.Transaction(func(tx *q.Query) error {
|
||||
err = updateBalance(q, uid, info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新交易状态
|
||||
trade, err := Trade.OnTradeCreated(tx, &OnTradeCreateData{
|
||||
TradeNo: tradeNo,
|
||||
TradeSuccessResult: *verified,
|
||||
// 生成账单
|
||||
err = q.Bill.Create(bill2.NewForRecharge(uid, Bill.GenNo(), info.GetSubject(), info.GetAmount(), trade))
|
||||
if err != nil {
|
||||
return core.NewServErr("生成账单失败", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新用户余额
|
||||
user, err := tx.User.
|
||||
Where(tx.User.ID.Eq(trade.UserID)).Take()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tx.User.
|
||||
Where(tx.User.ID.Eq(user.ID)).
|
||||
UpdateSimple(tx.User.Balance.Value(user.Balance.Add(trade.Amount)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return core.NewServErr("更新用户余额失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func updateBalance(q *q.Query, uid int32, info *RechargeProductInfo) (err error) {
|
||||
|
||||
// 更新余额
|
||||
user, err := q.User.
|
||||
Where(q.User.ID.Eq(uid)).Take()
|
||||
if err != nil {
|
||||
return core.NewServErr("查询用户失败", err)
|
||||
}
|
||||
|
||||
var amount = user.Balance.Add(info.GetAmount())
|
||||
if amount.IsNegative() {
|
||||
return core.NewServErr("用户余额不足")
|
||||
}
|
||||
|
||||
_, err = q.User.
|
||||
Where(q.User.ID.Eq(user.ID)).
|
||||
UpdateSimple(q.User.Balance.Value(amount))
|
||||
if err != nil {
|
||||
return core.NewServErr("更新用户余额失败", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *userService) RechargeCancel(tradeNo string, now time.Time) error {
|
||||
panic("not implemented")
|
||||
func userBalanceKey(uid int32) string {
|
||||
return fmt.Sprintf("user:%d:balance", uid)
|
||||
}
|
||||
|
||||
func (s *userService) RechargeRefund(tradeNo string, now time.Time) error {
|
||||
panic("not implemented")
|
||||
type RechargeProductInfo struct {
|
||||
Amount int `json:"amount"`
|
||||
}
|
||||
|
||||
func (r *RechargeProductInfo) GetType() trade2.Type {
|
||||
return trade2.TypeRecharge
|
||||
}
|
||||
|
||||
func (r *RechargeProductInfo) GetSubject() string {
|
||||
return fmt.Sprintf("账户充值 - " + 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 trade2.Type) (trade2.ProductInfo, bool) {
|
||||
if t == trade2.TypeRecharge {
|
||||
return &RechargeProductInfo{}, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (u UserOnTradeComplete) OnTradeComplete(info trade2.ProductInfo, trade *m.Trade) error {
|
||||
return User.UpdateBalanceByTrade(trade.UserID, info.(*RechargeProductInfo), trade)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user