fix: 添加代理生成卡密余额检查和扣费逻辑
- 检查代理余额是否足够 - 检查并限制生成数量(1-100) - 使用事务确保数据一致性 - 扣除代理余额 - 记录消费记录 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -235,6 +236,12 @@ func handleGenerateCards(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 限制最大生成数量
|
||||
if req.Quantity <= 0 || req.Quantity > 100 {
|
||||
response.Error(c, 400, "生成数量必须在1-100之间")
|
||||
return
|
||||
}
|
||||
|
||||
// 兼容 app_id 和 application_id
|
||||
appID := req.ApplicationID
|
||||
if appID == 0 {
|
||||
@@ -254,13 +261,24 @@ func handleGenerateCards(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取卡类信息以计算价格
|
||||
var cardType model.CardType
|
||||
if err := database.DB.First(&cardType, req.CardTypeID).Error; err != nil {
|
||||
response.Error(c, 404, "卡类不存在")
|
||||
// 计算总价格
|
||||
totalPrice := agentCardType.Price * float64(req.Quantity)
|
||||
|
||||
// 获取代理余额并检查是否足够
|
||||
var user model.User
|
||||
if err := database.DB.First(&user, userID).Error; err != nil {
|
||||
response.Error(c, 404, "用户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Balance < totalPrice {
|
||||
response.Error(c, 400, fmt.Sprintf("余额不足,当前余额: %.2f,需要: %.2f", user.Balance, totalPrice))
|
||||
return
|
||||
}
|
||||
|
||||
// 使用事务确保数据一致性
|
||||
tx := database.DB.Begin()
|
||||
|
||||
cards := make([]model.Card, req.Quantity)
|
||||
for i := 0; i < req.Quantity; i++ {
|
||||
cards[i] = model.Card{
|
||||
@@ -273,11 +291,36 @@ func handleGenerateCards(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&cards).Error; err != nil {
|
||||
if err := tx.Create(&cards).Error; err != nil {
|
||||
tx.Rollback()
|
||||
response.Error(c, 500, "生成卡密失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 扣除余额
|
||||
if err := tx.Model(&user).Update("balance", user.Balance-totalPrice).Error; err != nil {
|
||||
tx.Rollback()
|
||||
response.Error(c, 500, "扣除余额失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 记录消费记录
|
||||
consumeRecord := model.RechargeRecord{
|
||||
UserID: userID,
|
||||
OrderNo: fmt.Sprintf("CARD%d%d", userID, time.Now().UnixNano()),
|
||||
Amount: -totalPrice,
|
||||
Status: "success",
|
||||
PaymentType: "balance",
|
||||
Remark: fmt.Sprintf("生成卡密 %d 张", req.Quantity),
|
||||
}
|
||||
if err := tx.Create(&consumeRecord).Error; err != nil {
|
||||
tx.Rollback()
|
||||
response.Error(c, 500, "记录消费失败")
|
||||
return
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
|
||||
// 返回生成的卡号
|
||||
codes := make([]string, req.Quantity)
|
||||
for i, card := range cards {
|
||||
@@ -285,8 +328,10 @@ func handleGenerateCards(c *gin.Context) {
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"count": req.Quantity,
|
||||
"codes": codes,
|
||||
"count": req.Quantity,
|
||||
"codes": codes,
|
||||
"totalPrice": totalPrice,
|
||||
"balance": user.Balance - totalPrice,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user