互动
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.

208 lines
5.4 KiB

5 years ago
5 years ago
  1. package pay_service
  2. import (
  3. "go.uber.org/zap"
  4. "hudongzhuanjia/logger"
  5. "hudongzhuanjia/models"
  6. "hudongzhuanjia/utils/define"
  7. "math"
  8. "time"
  9. )
  10. var orderDelayQueue = make(chan *models.UserOrder, math.MaxInt8)
  11. func PutOrderDelayQueue(order *models.UserOrder) {
  12. orderDelayQueue <- order
  13. }
  14. func loopOrder() {
  15. orders, err := models.GetUserOrdersByStatus(0, 3)
  16. if err != nil {
  17. panic(err)
  18. }
  19. for _, order := range orders {
  20. PutOrderDelayQueue(order)
  21. }
  22. defer func() {
  23. if err := recover(); err != nil {
  24. logger.Error("订单轮询查询: panic 恢复错误", err)
  25. }
  26. // 重启
  27. time.Sleep(5 * time.Second)
  28. loopOrder()
  29. }()
  30. for {
  31. select {
  32. case order, ok := <-orderDelayQueue:
  33. if !ok {
  34. panic("通道异常关闭")
  35. }
  36. if order.ExpireAt <= time.Now().Unix() { // 订单超时
  37. if order.Status == 0 {
  38. go HandleTimeout(order)
  39. }
  40. continue
  41. }
  42. if order.Status == 0 {
  43. res, err := OrderQuery(order.OutTradeNo)
  44. if err != nil {
  45. logger.Error("查询订单出现错误: 错误原因-->", err.Error(), "交易订单号-->", order.OutTradeNo)
  46. orderDelayQueue <- order // 重新进入队列
  47. continue
  48. }
  49. if res["trade_state"] == define.CODE_TRADE_SUCCESS {
  50. go HandleSuccess(order)
  51. } else if res["trade_state"] == define.CODE_TRADE_REFUND {
  52. order.Status = 3
  53. orderDelayQueue <- order
  54. continue
  55. } else {
  56. orderDelayQueue <- order
  57. continue
  58. }
  59. } else if order.Status == 3 {
  60. res, err := QueryRefund(order.OutTradeNo)
  61. if err != nil {
  62. logger.Error("退款订单查询错误: 错误原因-->", err.Error(), "交易订单号-->", order.OutTradeNo)
  63. continue
  64. }
  65. order.RefundAccount = res.RefundList[0].RefundAccount
  66. order.RefundRecvAccount = res.RefundList[0].RefundRecvAccout
  67. order.Status = 4
  68. _, err = models.Update(order.Id, order, "refund_account", "refund_recv_account", "status")
  69. if err != nil {
  70. logger.Error("退款状态改变错误: 错误原因-->", err, "交易订单号-->", order.OutTradeNo)
  71. continue
  72. }
  73. }
  74. }
  75. }
  76. }
  77. func HandleTimeout(order *models.UserOrder) error {
  78. // 退还库存
  79. if order.GoodType == 4 {
  80. err := HandleCancelOrder(order.OutTradeNo)
  81. if err != nil {
  82. logger.Error(err)
  83. }
  84. }
  85. return nil
  86. }
  87. func init() {
  88. //go loopTransfer()
  89. }
  90. var transferDelayQueue = make(chan *transferDelayQueueParam, math.MaxInt8)
  91. type transferDelayQueueParam struct {
  92. first bool // 首次跳过
  93. Retries int `json:"retries"` // 尝试次数
  94. Delay int `json:"delay"` // 延迟时间, 单位second
  95. Amount int `json:"amount"` // 转账金额
  96. Desc string `json:"desc"` // 转账描述
  97. OpenId string `json:"open_id"` // 被转账人
  98. PartnerTradeNo string `json:"partner_trade_no"` // 转账账单单号
  99. }
  100. func loopTransfer() {
  101. //初始化
  102. transfers, err := models.GetUserTransferByStatus(0, 1, 3)
  103. if err != nil {
  104. panic(err)
  105. }
  106. transferDelayQueue = make(chan *transferDelayQueueParam, math.MaxInt8)
  107. for _, transfer := range transfers {
  108. transferDelayQueue <- &transferDelayQueueParam{
  109. first: true,
  110. Retries: 5,
  111. Delay: 2 * 60,
  112. Amount: transfer.PaymentAmount,
  113. Desc: transfer.Desc,
  114. OpenId: transfer.OpenId,
  115. PartnerTradeNo: transfer.PartnerTradeNo,
  116. }
  117. }
  118. defer func() {
  119. if errRec := recover(); errRec != nil {
  120. logger.Error("转账轮询 loop transfer panic", zap.Any("错误原因", errRec))
  121. }
  122. loopTransfer()
  123. }()
  124. for {
  125. select {
  126. case param, ok := <-transferDelayQueue:
  127. if !ok {
  128. panic("转账延迟通道异常关闭")
  129. }
  130. // 尝试次数
  131. if param.Retries <= 0 {
  132. logger.Info("微信转账尝试3次失败", zap.String("转账账单单号", param.PartnerTradeNo))
  133. userTransfer := new(models.UserTransfer)
  134. userTransfer.Status = 4
  135. _, err = userTransfer.UpdateByPartnerTradeNo(param.PartnerTradeNo)
  136. if err != nil {
  137. logger.Info("微信转账更新状态失败", zap.String("失败原因", err.Error()),
  138. zap.String("转账账单单号", param.PartnerTradeNo))
  139. }
  140. continue
  141. } else {
  142. param.Retries--
  143. }
  144. if !param.first {
  145. time.Sleep(time.Duration(param.Delay) * time.Second)
  146. }
  147. param.first = false
  148. res, err := TransferInfo(param.PartnerTradeNo)
  149. if err != nil {
  150. logger.Error("微信转账查询出现的错误", zap.String("错误原因", err.Error()),
  151. zap.String("转账账单", param.PartnerTradeNo))
  152. transferDelayQueue <- param
  153. continue
  154. }
  155. if res.Status == define.CODE_SUCCESS {
  156. continue
  157. } else if res.Status == define.CODE_TRANSFER_PROCESSING {
  158. transferDelayQueue <- param
  159. continue
  160. } else {
  161. //失败 --> 重新转账
  162. _, err = Transfer(param.Desc, param.OpenId, param.PartnerTradeNo, param.Amount)
  163. if err != nil {
  164. logger.Error("微信转账出现的错误", zap.String("错误原因", err.Error()),
  165. zap.String("转账账单", param.PartnerTradeNo))
  166. }
  167. transferDelayQueue <- param // 重新确认
  168. continue
  169. }
  170. }
  171. }
  172. }
  173. func PutTransferDelayQueue(desc, openId, partnerTradeNo string, amount, retries, delay int) {
  174. if retries <= 0 {
  175. retries = 3
  176. }
  177. if delay == 0 {
  178. delay = 30
  179. }
  180. transferDelayQueue <- &transferDelayQueueParam{
  181. first: true,
  182. Retries: retries,
  183. Delay: delay,
  184. Amount: amount,
  185. Desc: desc,
  186. OpenId: openId,
  187. PartnerTradeNo: partnerTradeNo,
  188. }
  189. }