topup.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package model
  2. import (
  3. "errors"
  4. "fmt"
  5. "one-api/common"
  6. "one-api/logger"
  7. "gorm.io/gorm"
  8. )
  9. type TopUp struct {
  10. Id int `json:"id"`
  11. UserId int `json:"user_id" gorm:"index"`
  12. Amount int64 `json:"amount"`
  13. Money float64 `json:"money"`
  14. TradeNo string `json:"trade_no" gorm:"unique;type:varchar(255);index"`
  15. CreateTime int64 `json:"create_time"`
  16. CompleteTime int64 `json:"complete_time"`
  17. Status string `json:"status"`
  18. }
  19. func (topUp *TopUp) Insert() error {
  20. var err error
  21. err = DB.Create(topUp).Error
  22. return err
  23. }
  24. func (topUp *TopUp) Update() error {
  25. var err error
  26. err = DB.Save(topUp).Error
  27. return err
  28. }
  29. func GetTopUpById(id int) *TopUp {
  30. var topUp *TopUp
  31. var err error
  32. err = DB.Where("id = ?", id).First(&topUp).Error
  33. if err != nil {
  34. return nil
  35. }
  36. return topUp
  37. }
  38. func GetTopUpByTradeNo(tradeNo string) *TopUp {
  39. var topUp *TopUp
  40. var err error
  41. err = DB.Where("trade_no = ?", tradeNo).First(&topUp).Error
  42. if err != nil {
  43. return nil
  44. }
  45. return topUp
  46. }
  47. func Recharge(referenceId string, customerId string) (err error) {
  48. if referenceId == "" {
  49. return errors.New("未提供支付单号")
  50. }
  51. var quota float64
  52. topUp := &TopUp{}
  53. refCol := "`trade_no`"
  54. if common.UsingPostgreSQL {
  55. refCol = `"trade_no"`
  56. }
  57. err = DB.Transaction(func(tx *gorm.DB) error {
  58. err := tx.Set("gorm:query_option", "FOR UPDATE").Where(refCol+" = ?", referenceId).First(topUp).Error
  59. if err != nil {
  60. return errors.New("充值订单不存在")
  61. }
  62. if topUp.Status != common.TopUpStatusPending {
  63. return errors.New("充值订单状态错误")
  64. }
  65. topUp.CompleteTime = common.GetTimestamp()
  66. topUp.Status = common.TopUpStatusSuccess
  67. err = tx.Save(topUp).Error
  68. if err != nil {
  69. return err
  70. }
  71. quota = topUp.Money * common.QuotaPerUnit
  72. err = tx.Model(&User{}).Where("id = ?", topUp.UserId).Updates(map[string]interface{}{"stripe_customer": customerId, "quota": gorm.Expr("quota + ?", quota)}).Error
  73. if err != nil {
  74. return err
  75. }
  76. return nil
  77. })
  78. if err != nil {
  79. return errors.New("充值失败," + err.Error())
  80. }
  81. RecordLog(topUp.UserId, LogTypeTopup, fmt.Sprintf("使用在线充值成功,充值金额: %v,支付金额:%d", logger.FormatQuota(int(quota)), topUp.Amount))
  82. return nil
  83. }
  84. func RechargeCreem(referenceId string, customerEmail string, customerName string) (err error) {
  85. if referenceId == "" {
  86. return errors.New("未提供支付单号")
  87. }
  88. var quota int64
  89. topUp := &TopUp{}
  90. refCol := "`trade_no`"
  91. if common.UsingPostgreSQL {
  92. refCol = `"trade_no"`
  93. }
  94. err = DB.Transaction(func(tx *gorm.DB) error {
  95. err := tx.Set("gorm:query_option", "FOR UPDATE").Where(refCol+" = ?", referenceId).First(topUp).Error
  96. if err != nil {
  97. return errors.New("充值订单不存在")
  98. }
  99. if topUp.Status != common.TopUpStatusPending {
  100. return errors.New("充值订单状态错误")
  101. }
  102. topUp.CompleteTime = common.GetTimestamp()
  103. topUp.Status = common.TopUpStatusSuccess
  104. err = tx.Save(topUp).Error
  105. if err != nil {
  106. return err
  107. }
  108. // Creem 直接使用 Amount 作为充值额度(整数)
  109. quota = topUp.Amount
  110. // 构建更新字段,优先使用邮箱,如果邮箱为空则使用用户名
  111. updateFields := map[string]interface{}{
  112. "quota": gorm.Expr("quota + ?", quota),
  113. }
  114. // 如果有客户邮箱,尝试更新用户邮箱(仅当用户邮箱为空时)
  115. if customerEmail != "" {
  116. // 先检查用户当前邮箱是否为空
  117. var user User
  118. err = tx.Where("id = ?", topUp.UserId).First(&user).Error
  119. if err != nil {
  120. return err
  121. }
  122. // 如果用户邮箱为空,则更新为支付时使用的邮箱
  123. if user.Email == "" {
  124. updateFields["email"] = customerEmail
  125. }
  126. }
  127. err = tx.Model(&User{}).Where("id = ?", topUp.UserId).Updates(updateFields).Error
  128. if err != nil {
  129. return err
  130. }
  131. return nil
  132. })
  133. if err != nil {
  134. return errors.New("充值失败," + err.Error())
  135. }
  136. RecordLog(topUp.UserId, LogTypeTopup, fmt.Sprintf("使用Creem充值成功,充值额度: %v,支付金额:%.2f", quota, topUp.Money))
  137. return nil
  138. }