active.cash.out.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package shanghu
  2. import (
  3. "duoduo/apis/common"
  4. "duoduo/apis/shanghu/models"
  5. "duoduo/models/shanghu"
  6. "duoduo/tools/app"
  7. "errors"
  8. "fmt"
  9. "github.com/gin-gonic/gin"
  10. "github.com/go-pay/gopay"
  11. "github.com/shopspring/decimal"
  12. "time"
  13. )
  14. func ActiveCashOut(c *gin.Context) {
  15. var inData models.PayCashOutRequest
  16. var merchantAccountSql shanghu.MerchantAccount
  17. var clientAccountSql shanghu.MerchantClientAccount
  18. var cashOut shanghu.CashOut
  19. var trans []models.TransferDetailList
  20. var transDetail models.TransferDetailList
  21. err := c.ShouldBindJSON(&inData)
  22. if err != nil {
  23. app.Error(c, 400, err, err.Error())
  24. return
  25. }
  26. _, ok := GlobalCashOutMap[inData.OpenId]
  27. if ok {
  28. app.OK(c, nil, "正在提现中...")
  29. return
  30. }
  31. GlobalCashOutMap[inData.OpenId] = 1
  32. defer func() {
  33. delete(GlobalCashOutMap, inData.OpenId)
  34. }()
  35. if inData.Appid == "" { //appid 不能为空
  36. app.Error(c, 400, errors.New("AppID不能为空"), "AppID不能为空")
  37. return
  38. }
  39. if inData.Amount.Cmp(decimal.NewFromInt(500)) > 0 {
  40. app.Error(c, 400, errors.New("单笔金额不能大于500"), "单笔金额不能大于500")
  41. return
  42. }
  43. if inData.Amount.Cmp(decimal.NewFromInt(1)) < 0 {
  44. app.Error(c, 400, errors.New("单笔金额不能小于1"), "单笔金额不能大于1")
  45. return
  46. }
  47. //
  48. cashOut.OpenID = inData.OpenId
  49. cashOut.AppID = inData.Appid
  50. cashOut.Status = 1 //提现中
  51. status := []int{1, 3} //提现中、金额待扣减
  52. cashNum := cashOut.GetCashOutByStatusNum(status)
  53. if cashNum > 0 {
  54. app.Error(c, 400, errors.New("有一笔交易正在提现中"), "有一笔交易正在提现中")
  55. return
  56. }
  57. //校验金额是否够
  58. if inData.AccountType == "client" {
  59. clientAccountSql.ClientOpenID = inData.OpenId
  60. clientAccountInfo, err := clientAccountSql.GetClientAccount()
  61. if err != nil {
  62. app.Error(c, 400, err, err.Error())
  63. return
  64. }
  65. if inData.Amount.Cmp(clientAccountInfo.Amount) > 0 {
  66. app.Error(c, 400, errors.New("账号余额不够"), "账号余额不够")
  67. return
  68. }
  69. var client shanghu.MerchantClientUser
  70. client.Code = "7jb6"
  71. clientInfo, _ := client.GetUserInfoByCode()
  72. if clientInfo.ClientOpenID == inData.OpenId {
  73. cashOut.Fee = decimal.NewFromInt(0)
  74. } else {
  75. cashOut.Fee = inData.Amount.Mul(decimal.NewFromFloat32(0.05))
  76. }
  77. } else if inData.AccountType == "merchant" {
  78. merchantAccountSql.MerchantOpenID = inData.OpenId
  79. merchantAccountInfo, err := merchantAccountSql.GetMerchantAccount()
  80. if err != nil {
  81. app.Error(c, 400, err, err.Error())
  82. return
  83. }
  84. if inData.Amount.Cmp(merchantAccountInfo.Amount) > 0 {
  85. app.Error(c, 400, errors.New("账号余额不够"), "账号余额不够")
  86. return
  87. }
  88. cashOut.Fee = decimal.NewFromInt(0)
  89. } else {
  90. app.Error(c, 400, errors.New("账户类型错误"), "账户类型错误")
  91. return
  92. }
  93. clientV3, err := NewWechatServiceV3(inData.Appid)
  94. if err != nil {
  95. app.Error(c, 400, err, err.Error())
  96. return
  97. }
  98. userName, err := clientV3.V3EncryptText(inData.UserName)
  99. if err != nil {
  100. app.Error(c, 400, err, err.Error())
  101. return
  102. }
  103. transDetail.OutDetailNo = common.GetRandomString(32)
  104. transDetail.TransferAmount = inData.Amount.Sub(cashOut.Fee).Mul(decimal.NewFromInt(100)).IntPart()
  105. transDetail.UserName = userName
  106. transDetail.Openid = inData.OpenId
  107. transDetail.TransferRemark = "提现"
  108. trans = append(trans, transDetail)
  109. partnerTradeNo := common.GetRandomString(32)
  110. var cashOutCreate shanghu.CashOut
  111. //创建提现记录
  112. cashOutCreate.AppID = inData.Appid
  113. cashOutCreate.Status = 1 //提现中
  114. cashOutCreate.OpenID = inData.OpenId
  115. cashOutCreate.Amount = inData.Amount
  116. cashOutCreate.CreatedAt = time.Now()
  117. cashOutCreate.UpdatedAt = time.Now()
  118. cashOutCreate.PartnerTradeNo = partnerTradeNo
  119. cashOutCreate.Fee = cashOut.Fee
  120. cashOutInfo, err := cashOutCreate.Create()
  121. if err != nil {
  122. app.Error(c, 400, err, err.Error())
  123. return
  124. }
  125. var bMap []gopay.BodyMap
  126. bm := make(gopay.BodyMap)
  127. bm.Set("appid", inData.Appid)
  128. bm.Set("out_batch_no", partnerTradeNo)
  129. bm.Set("batch_name", "提现")
  130. bm.Set("batch_remark", "提现")
  131. bm.Set("total_amount", inData.Amount.Sub(cashOut.Fee).Mul(decimal.NewFromInt(100)).IntPart())
  132. bm.Set("total_num", 1)
  133. bMap = append(bMap, structToMap(&transDetail))
  134. bm.Set("transfer_detail_list", bMap)
  135. bm.Set("transfer_scene_id", "1001")
  136. fmt.Println(bm.JsonBody())
  137. reply, err := clientV3.V3Transfer(c, bm)
  138. if err != nil {
  139. cashOut.ID = cashOutInfo.ID
  140. cashOut.FailRes = err.Error()
  141. cashOut.Status = 2 //提现失败
  142. cashOut.UpdateMerchantStatus()
  143. app.Error(c, 500, err, err.Error())
  144. return
  145. }
  146. if reply.Code != 0 {
  147. cashOut.ID = cashOutInfo.ID
  148. cashOut.FailRes = reply.Error
  149. cashOut.Status = 2 //提现失败
  150. cashOut.UpdateMerchantStatus()
  151. app.Error(c, 500, errors.New(reply.Error), reply.Error)
  152. return
  153. }
  154. cashOut.WxPartnerTradeNo = reply.Response.BatchId
  155. cashOut.PartnerTradeNo = reply.Response.OutBatchNo
  156. cashOut.UpdateCashOutWxBachNo()
  157. app.OK(c, nil, app.Success)
  158. }