api_util.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package utils
  2. import (
  3. "sfbase/core"
  4. // "context"
  5. "fmt"
  6. "log"
  7. "sfbase/global"
  8. "sfbase/redis"
  9. "sfbase/utils"
  10. "sfis/db"
  11. "sfis/lock"
  12. "sfis/model"
  13. "sfis/model/response"
  14. "strings"
  15. "time"
  16. "github.com/gin-gonic/gin"
  17. "go.uber.org/zap"
  18. )
  19. func Check(appID string, productID int, c *gin.Context, getData func() ([]map[string]interface{}, int, error), param, ip string, concurrentTest bool) {
  20. lock.MainLock.Lock()
  21. userLock := lock.UserLockMap[appID]
  22. lock.MainLock.Unlock()
  23. var err error
  24. datas := []map[string]interface{}{}
  25. orderCode := ""
  26. errStr := ""
  27. /**
  28. 第二步:用户接口产品校验-加锁处理
  29. */
  30. //2.1 取用户接口状态校验-可加锁也可不加锁 这个没有太严谨
  31. //userLock.Lock()
  32. userProduct := &model.UserProduct{}
  33. db.GetSFISDB().First(userProduct, &model.UserProduct{AppID: appID, ProductID: productID})
  34. //userLock.Unlock()
  35. if userProduct.ID == 0 {
  36. response.FailWithDetailed(response.InterfaceDeleted, nil, "该用户接口未购买", c)
  37. return
  38. } else if userProduct.InterfaceStatus != 0 {
  39. response.FailWithDetailed(response.InterfaceDeleted, nil, "该用户接口暂不提供服务", c)
  40. return
  41. }
  42. //校验是否过期
  43. now := time.Now().Unix()
  44. end := userProduct.EndAt
  45. if now > end.Unix() {
  46. response.FailWithDetailed(response.InterfaceExpired, nil, "剩余量已过期", c)
  47. return
  48. }
  49. //校验每日调用上限
  50. limittodaykey := fmt.Sprintf("limittoday_%d_%d_%s", time.Now().Day(), productID, appID)
  51. limittoday := redis.GetInt("limit", limittodaykey)
  52. if limittoday >= userProduct.CallTimesLimitDay { //当天调用超过次数
  53. response.FailWithDetailed(response.MoreThanEveryDayDataNumberLimit, nil, "请求超过每日调用总量限制", c)
  54. return
  55. } else {
  56. if limittoday == 0 {
  57. _, max := utils.GetDayMinMax(time.Now())
  58. redis.Put("limit", limittodaykey, 0, int(max-now))
  59. }
  60. }
  61. //
  62. limitrate := fmt.Sprintf("limitrate_%d_%s", userProduct.ProductID, userProduct.AppID)
  63. Exists, _ := redis.Exists("limit", limitrate)
  64. if Exists {
  65. response.FailWithDetailed(response.CallRate, nil, "请求频率过快,请稍后重试", c)
  66. }
  67. //2.2 取用户(产品余量|钱包账户余额)校验-必须加锁
  68. costModel := userProduct.CostModel //扣费模式 0扣余量,1-扣余额
  69. product := GetProductByID(productID)
  70. userLock.Lock()
  71. log.Println(param + "锁住......")
  72. db.GetSFISDB().First(userProduct, &model.UserProduct{AppID: appID, ProductID: productID})
  73. // costModel = 0
  74. switch costModel {
  75. case 0:
  76. //按剩余量扣费
  77. datas, orderCode, err, errStr = costByLeftNum(getData, appID, productID, userProduct, product, param, ip)
  78. case 1:
  79. //按账户钱包余额扣费
  80. datas, orderCode, err, errStr = costByAccountBalance(getData, appID, productID, userProduct, product, param, ip)
  81. case 2:
  82. //优先扣剩余量,剩余量为0,扣钱包余额
  83. }
  84. userLock.Unlock()
  85. log.Println(param + "解锁......")
  86. if err == nil {
  87. db.GetQyfw().Save("user_data", map[string]interface{}{
  88. "app_id": appID,
  89. "result_num": len(datas),
  90. "result_content": datas,
  91. "order_code": orderCode,
  92. "status": 200,
  93. "user_product_id": userProduct.ID,
  94. "create_at": time.Now().Unix(),
  95. })
  96. limittodaykey := fmt.Sprintf("limittoday_%d_%d_%s", time.Now().Day(), userProduct.ProductID, userProduct.AppID)
  97. limitrate := fmt.Sprintf("limitrate_%d_%s", userProduct.ProductID, userProduct.AppID)
  98. rateTime := core.GetIntConf("base.session.interface_call_rate")
  99. redis.Incr("limit", limittodaykey)
  100. redis.Put("limit", limitrate, 1, rateTime)
  101. if !concurrentTest {
  102. response.FailWithDetailed(response.SUCCESS, datas, "OK", c)
  103. }
  104. } else {
  105. if strings.Contains(errStr, "不足") {
  106. response.FailWithDetailed(response.LeftNumEmpty, nil, errStr, c)
  107. } else {
  108. global.Logger.Error("数据库操作失败", zap.Any("error:", err))
  109. response.FailWithDetailed(response.QueryError, nil, "内部错误", c)
  110. }
  111. }
  112. }