billing.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package controller
  2. import (
  3. "github.com/QuantumNous/new-api/common"
  4. "github.com/QuantumNous/new-api/dto"
  5. "github.com/QuantumNous/new-api/model"
  6. "github.com/QuantumNous/new-api/setting/operation_setting"
  7. "github.com/gin-gonic/gin"
  8. )
  9. func GetSubscription(c *gin.Context) {
  10. var remainQuota int
  11. var usedQuota int
  12. var err error
  13. var token *model.Token
  14. var expiredTime int64
  15. if common.DisplayTokenStatEnabled {
  16. tokenId := c.GetInt("token_id")
  17. token, err = model.GetTokenById(tokenId)
  18. expiredTime = token.ExpiredTime
  19. remainQuota = token.RemainQuota
  20. usedQuota = token.UsedQuota
  21. } else {
  22. userId := c.GetInt("id")
  23. remainQuota, err = model.GetUserQuota(userId, false)
  24. usedQuota, err = model.GetUserUsedQuota(userId)
  25. }
  26. if expiredTime <= 0 {
  27. expiredTime = 0
  28. }
  29. if err != nil {
  30. openAIError := dto.OpenAIError{
  31. Message: err.Error(),
  32. Type: "upstream_error",
  33. }
  34. c.JSON(200, gin.H{
  35. "error": openAIError,
  36. })
  37. return
  38. }
  39. quota := remainQuota + usedQuota
  40. amount := float64(quota)
  41. // OpenAI 兼容接口中的 *_USD 字段含义保持“额度单位”对应值:
  42. // 我们将其解释为以“站点展示类型”为准:
  43. // - USD: 直接除以 QuotaPerUnit
  44. // - CNY: 先转 USD 再乘汇率
  45. // - TOKENS: 直接使用 tokens 数量
  46. switch operation_setting.GetQuotaDisplayType() {
  47. case operation_setting.QuotaDisplayTypeCNY:
  48. amount = amount / common.QuotaPerUnit * operation_setting.USDExchangeRate
  49. case operation_setting.QuotaDisplayTypeTokens:
  50. // amount 保持 tokens 数值
  51. default:
  52. amount = amount / common.QuotaPerUnit
  53. }
  54. if token != nil && token.UnlimitedQuota {
  55. amount = 100000000
  56. }
  57. subscription := OpenAISubscriptionResponse{
  58. Object: "billing_subscription",
  59. HasPaymentMethod: true,
  60. SoftLimitUSD: amount,
  61. HardLimitUSD: amount,
  62. SystemHardLimitUSD: amount,
  63. AccessUntil: expiredTime,
  64. }
  65. c.JSON(200, subscription)
  66. return
  67. }
  68. func GetUsage(c *gin.Context) {
  69. var quota int
  70. var err error
  71. var token *model.Token
  72. if common.DisplayTokenStatEnabled {
  73. tokenId := c.GetInt("token_id")
  74. token, err = model.GetTokenById(tokenId)
  75. quota = token.UsedQuota
  76. } else {
  77. userId := c.GetInt("id")
  78. quota, err = model.GetUserUsedQuota(userId)
  79. }
  80. if err != nil {
  81. openAIError := dto.OpenAIError{
  82. Message: err.Error(),
  83. Type: "new_api_error",
  84. }
  85. c.JSON(200, gin.H{
  86. "error": openAIError,
  87. })
  88. return
  89. }
  90. amount := float64(quota)
  91. switch operation_setting.GetQuotaDisplayType() {
  92. case operation_setting.QuotaDisplayTypeCNY:
  93. amount = amount / common.QuotaPerUnit * operation_setting.USDExchangeRate
  94. case operation_setting.QuotaDisplayTypeTokens:
  95. // tokens 保持原值
  96. default:
  97. amount = amount / common.QuotaPerUnit
  98. }
  99. usage := OpenAIUsageResponse{
  100. Object: "list",
  101. TotalUsage: amount * 100,
  102. }
  103. c.JSON(200, usage)
  104. return
  105. }