topup.go 4.1 KB

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