api_util.go 3.7 KB

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