互动
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

260 lines
6.9 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. package client
  2. import (
  3. "go.uber.org/zap"
  4. "hudongzhuanjia/controllers"
  5. "hudongzhuanjia/libs/filter"
  6. "hudongzhuanjia/logger"
  7. "hudongzhuanjia/models"
  8. pay_service "hudongzhuanjia/services/pay"
  9. red_envelope_service "hudongzhuanjia/services/red_envelope"
  10. "hudongzhuanjia/utils"
  11. "hudongzhuanjia/utils/code"
  12. "strings"
  13. "time"
  14. )
  15. var MaxQueueSize = 10000
  16. var RequestLimit = 60 * time.Second
  17. var GetRedPackQueue = make(chan int64, MaxQueueSize)
  18. func loopGetRedPack() {
  19. redPacks, err := models.GetRedPacksByStatus(1)
  20. if err != nil {
  21. panic(err)
  22. }
  23. // 保证容量足够
  24. GetRedPackQueue = make(chan int64, MaxQueueSize+len(redPacks))
  25. // 初始化
  26. for _, redPack := range redPacks {
  27. GetRedPackQueue <- redPack.Id
  28. }
  29. defer func() {
  30. if errRec := recover(); errRec != nil {
  31. logger.Error("用户转账轮询发生错误",
  32. zap.String("函数", "loopGetRedPack"), zap.Any("错误原因", errRec))
  33. }
  34. time.Sleep(5 * time.Second)
  35. loopGetRedPack()
  36. }()
  37. for {
  38. select {
  39. case redPackId, ok := <-GetRedPackQueue:
  40. if !ok {
  41. panic("GetRedPackQueue通道关闭")
  42. }
  43. time.Sleep(RequestLimit) // 请求频率
  44. redPack := new(models.LiveRedPack)
  45. exist, err := models.GetById(redPack, redPackId)
  46. if err != nil {
  47. GetRedPackQueue <- redPackId
  48. logger.Error("获取LiveRedPack表数据出现错误",
  49. zap.Any("错误原因", err), zap.Int64("LiveRedPack表的id", redPack.Id))
  50. continue
  51. }
  52. if !exist {
  53. logger.Error("不存在LiveRedPack表数据", zap.Int64("LiveRedPack表的id", redPack.Id))
  54. continue
  55. }
  56. // todo: 增加一个查询机制 --查询此次付款是否成功
  57. // todo: 是否需要发放系统通知
  58. resp, err := pay_service.TransferInfo(redPack.TransferNo)
  59. if err != nil {
  60. GetRedPackQueue <- redPackId
  61. logger.Error("微信企业转账查询API",
  62. zap.Any("错误原因", err), zap.Int64("LiveRedPack表的id", redPack.Id))
  63. continue
  64. }
  65. if resp.Status == pay_service.CODE_FAIL { // 转账失败
  66. _, err = pay_service.Transfer("欧轩互动-红包活动", redPack.OpenId, redPack.TransferNo, redPack.Amount)
  67. if err != nil {
  68. GetRedPackQueue <- redPackId
  69. logger.Error("微信企业转账API",
  70. zap.Any("错误原因", err), zap.Int64("LiveRedPack表的id", redPack.Id))
  71. continue
  72. }
  73. _, err = redPack.UpdateStatusById(redPack.Id, 2)
  74. if err != nil {
  75. GetRedPackQueue <- redPackId
  76. logger.Error("微信企业转账,LiveRedPack表更新错误",
  77. zap.Any("错误原因", err), zap.Int64("LiveRedPack表id", redPack.Id))
  78. continue
  79. }
  80. } else if resp.Status == pay_service.CODE_SUCCESS {
  81. _, err = redPack.UpdateStatusById(redPack.Id, 2)
  82. if err != nil {
  83. logger.Error("微信企业查询,转账成功",
  84. zap.Any("错误原因", err), zap.Int64("LiveRedPack表id", redPack.Id))
  85. continue
  86. }
  87. }
  88. }
  89. }
  90. }
  91. var SendRedPackQueue = make(chan int64, MaxQueueSize)
  92. func loopSendRedPack() {
  93. redPackInfo :=
  94. defer func() {
  95. if err := recover(); err != nil {
  96. logger.Error("用户发送红包轮询出现错误",
  97. zap.String("函数", "loopSendRedPack"), zap.Any("错误", err))
  98. }
  99. time.Sleep(5 * time.Second)
  100. loopSendRedPack()
  101. }()
  102. for {
  103. select {
  104. case redPackInfoId, ok := <-SendRedPackQueue:
  105. if !ok {
  106. panic("SendRedPackQueue通道异常关闭")
  107. }
  108. }
  109. }
  110. }
  111. type LiveCtl struct {
  112. controllers.AuthorCtl
  113. //controllers.BaseCtl
  114. }
  115. // 详情
  116. func (t *LiveCtl) Detail() {
  117. activityId := t.MustGetInt64("activity_id")
  118. areaId := t.MustGetInt64("area_id")
  119. userId := t.MustGetUID()
  120. err := new(models.LiveViewer).Record(userId, activityId)
  121. t.CheckErr(err)
  122. live := new(models.LiveConfig)
  123. exist, err := live.GetByActivityId(activityId)
  124. t.CheckErr(err)
  125. t.Assert(exist, code.MSG_ACTIVITY_NOT_EXIST, "直播活动不存在")
  126. config := new(models.LiveConfigArea)
  127. exist, err = config.GetByActivityIdAndAreaId(activityId, areaId)
  128. t.CheckErr(err)
  129. if exist {
  130. live.SharePosterImg = config.MergeSharePoster
  131. }
  132. live.AdminLiveUrl = ""
  133. t.JSON(live)
  134. }
  135. func (t *LiveCtl) Like() {
  136. activityId := t.MustGetInt64("activity_id")
  137. //userId := t.MustGetUID()
  138. _, err := new(models.LiveConfig).Like(activityId)
  139. t.CheckErr(err)
  140. live := new(models.LiveConfig)
  141. exist, err := live.GetByActivityId(activityId)
  142. t.CheckErr(err)
  143. t.Assert(exist, code.MSG_ACTIVITY_NOT_EXIST, "直播活动不存在")
  144. t.JSON(map[string]interface{}{
  145. "like": live.LikeNum,
  146. "watch": live.WatchNum,
  147. })
  148. }
  149. func (t *LiveCtl) LoopQuery() {
  150. activityId := t.MustGetInt64("activity_id")
  151. live := new(models.LiveConfig)
  152. exist, err := live.GetByActivityId(activityId)
  153. t.CheckErr(err)
  154. t.Assert(exist, code.MSG_ACTIVITY_NOT_EXIST, "直播活动不存在")
  155. t.JSON(map[string]interface{}{
  156. "like": live.LikeNum,
  157. "watch": live.WatchNum,
  158. })
  159. }
  160. // 发送红包
  161. // 维护一个队列进行循环, 遍历是否付款成功
  162. func (t *LiveCtl) SendLiveRedPack() {
  163. userId := t.MustGetUID() // 用户 uid
  164. activityId := t.MustGetInt64("activity_id") // activity_id
  165. num := t.MustGetInt("num") // 红包数量
  166. amount := t.MustGetInt64("amount") // 金额
  167. prompt := t.MustGet("prompt") // 提示
  168. user := models.User{}
  169. exist, err := models.GetById(&user, userId)
  170. t.CheckErr(err)
  171. t.Assert(exist, code.MSG_USER_NOT_EXIST, "用户不存在")
  172. ip := strings.Split(t.Request.OriginRequest.RemoteAddr, ":")
  173. res, err := pay_service.UnifiedOrder("欧轩互动-直播红包", ip[0], user.Openid, amount)
  174. t.CheckErr(err)
  175. info := models.LiveRedPackInfo{}
  176. info.Amount = amount
  177. info.UserId = userId
  178. info.ActivityId = activityId
  179. info.Prompt = prompt
  180. info.IsDelete = false
  181. info.UpdatedAt = time.Now()
  182. info.CreatedAt = time.Now()
  183. _, err = info.Add()
  184. t.CheckErr(err)
  185. redPacks := red_envelope_service.GenRedPack(int(amount*100), num)
  186. for _, v := range redPacks {
  187. redPack := new(models.LiveRedPack)
  188. redPack.LiveRedPackInfoId = info.Id
  189. redPack.ActivityId = activityId
  190. redPack.Receiver = 0
  191. redPack.Amount = v
  192. redPack.CreatedAt = time.Now()
  193. redPack.UpdatedAt = time.Now()
  194. _, err = redPack.Add()
  195. t.CheckErr(err)
  196. }
  197. info.Prompt = filter.Replace(info.Prompt)
  198. t.JSON(info)
  199. }
  200. // 领取红包
  201. func (t *LiveCtl) GetRedPack() {
  202. liveRedPackInfoId := t.MustGetInt64("live_red_pack_info_id")
  203. userId := t.MustGetUID()
  204. user := models.User{}
  205. exist, err := models.GetById(&user, userId)
  206. t.CheckErr(err)
  207. t.Assert(exist, code.MSG_USER_NOT_EXIST, "不存在用户")
  208. redPack := new(models.LiveRedPack)
  209. exist, err = redPack.GetByInfoId(liveRedPackInfoId)
  210. t.CheckErr(err)
  211. if !exist {
  212. // 通知其他的人
  213. t.ERROR("红包被领完了", code.MSG_LIVE_RED_PACK_NOT_EXIST)
  214. return
  215. }
  216. // 乐观锁 ==> 防止并发
  217. redPack.OpenId = user.Openid
  218. redPack.Receiver = user.Id
  219. redPack.TransferType = 1
  220. redPack.TransferNo = utils.RandomStr(32)
  221. row, err := redPack.UpdateStatusById(redPack.Id, 1)
  222. t.CheckErr(err)
  223. if row != 1 {
  224. t.ERROR("红包被领完了", code.MSG_LIVE_RED_PACK_NOT_EXIST)
  225. return
  226. }
  227. GetRedPackQueue <- redPack.Id // 进入队列
  228. t.JSON(redPack)
  229. }