蛋蛋星球-客户端
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.
 
 
 
 
 

255 lines
8.6 KiB

  1. package svc
  2. import (
  3. "applet/app/db"
  4. "applet/app/e"
  5. md2 "applet/app/md"
  6. "applet/app/utils"
  7. "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
  8. "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
  9. "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
  10. "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
  11. "errors"
  12. "github.com/gin-gonic/gin"
  13. "github.com/shopspring/decimal"
  14. "math"
  15. "strings"
  16. "time"
  17. )
  18. func CheckWithdraw(c *gin.Context, amount string) (err error, realAmount, fee string, isAuto, isFirst bool) {
  19. realAmount = amount
  20. user := GetUser(c)
  21. now := time.Now()
  22. amountValue, _ := decimal.NewFromString(amount)
  23. //1、查询 fin_withdraw_setting 提现设置表
  24. finWithdrawSettingDb := implement.NewFinWithdrawSettingDb(db.Db)
  25. withdrawSetting, err := finWithdrawSettingDb.FinWithdrawSettingGetOne()
  26. if err != nil {
  27. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  28. return
  29. }
  30. //2、判断是否为第一次提现
  31. var isCompleteFirstWithdraw bool
  32. has, err := db.Db.Where("uid =?", user.Id).Get(model.FinWithdrawApply{})
  33. if !has { //第一次提现
  34. isFirst = true
  35. var firstWithdrawSet md.FirstWithdrawSet
  36. utils.Unserialize([]byte(withdrawSetting.FrequencySet), &firstWithdrawSet)
  37. if firstWithdrawSet.IsNeedRealName == 0 && firstWithdrawSet.FirstWithdrawAmountLimit >= amount {
  38. isCompleteFirstWithdraw = true
  39. }
  40. }
  41. //2、判断“是否实名”
  42. if isCompleteFirstWithdraw && withdrawSetting.IsRealName == 1 && user.IsRealName != 1 {
  43. return errors.New("非实名用户不可提现"), realAmount, fee, isAuto, isFirst
  44. }
  45. //3、判断“提现金额”
  46. if isCompleteFirstWithdraw && utils.StrToFloat64(withdrawSetting.WithdrawAmountLimit) > 0 {
  47. withdrawAmountLimitValue, _ := decimal.NewFromString(withdrawSetting.WithdrawAmountLimit)
  48. if amountValue.LessThan(withdrawAmountLimitValue) {
  49. return errors.New("非可提现金额"), realAmount, fee, isAuto, isFirst
  50. }
  51. }
  52. //4、判断“提现倍数”
  53. if isCompleteFirstWithdraw && utils.StrToFloat64(withdrawSetting.WithdrawMultipleLimit) > 0 {
  54. result := utils.StrToFloat64(amount) / utils.StrToFloat64(withdrawSetting.WithdrawMultipleLimit)
  55. // 检查结果是否非常接近一个整数
  56. roundedResult := math.Round(result)
  57. if !(math.Abs(roundedResult-result) < 1e-9) {
  58. return errors.New("非可提现倍数"), realAmount, fee, isAuto, isFirst
  59. }
  60. }
  61. //5、验证会员等级
  62. if isCompleteFirstWithdraw && withdrawSetting.VipLevelLimit > 0 && withdrawSetting.VipLevelLimit > user.Level {
  63. return errors.New("非可提现会员等级"), realAmount, fee, isAuto, isFirst
  64. }
  65. //6、 验证小数点
  66. if isCompleteFirstWithdraw && withdrawSetting.IsSupportDecimalPoint == 0 && strings.Contains(amount, ".") {
  67. return errors.New("不支持的提现金额"), realAmount, fee, isAuto, isFirst
  68. }
  69. //7、验证时段
  70. if withdrawSetting.WithdrawTimeInterval != "" {
  71. withdrawTimeInterval := strings.Split(withdrawSetting.WithdrawTimeInterval, "-")
  72. // 定义要比较的时间格式
  73. layout := "15:04"
  74. // 解析给定的时间字符串
  75. start, _ := time.Parse(layout, withdrawTimeInterval[0])
  76. end, _ := time.Parse(layout, withdrawTimeInterval[1])
  77. // 设置为今天的日期
  78. start = time.Date(now.Year(), now.Month(), now.Day(), start.Hour(), start.Minute(), 0, 0, now.Location())
  79. end = time.Date(now.Year(), now.Month(), now.Day(), end.Hour(), end.Minute(), 0, 0, now.Location())
  80. // 如果结束时间小于开始时间,说明跨天了
  81. if end.Before(start) {
  82. if !(now.After(start) || now.Before(end)) {
  83. return errors.New("非可提现时间段"), realAmount, fee, isAuto, isFirst
  84. }
  85. } else { // 否则,在同一天内比较
  86. if !(now.After(start) && now.Before(end)) {
  87. return errors.New("非可提现时间段"), realAmount, fee, isAuto, isFirst
  88. }
  89. }
  90. }
  91. //8、验证“提现频率”
  92. var frequency md.WithdrawFrequencySettingStruct
  93. utils.Unserialize([]byte(withdrawSetting.FrequencySet), &frequency)
  94. if frequency.Duration == 2 {
  95. day := now.Weekday()
  96. if !utils.InArr(utils.IntToStr(int(day)), frequency.Num) {
  97. return errors.New("非可提现日期"), realAmount, fee, isAuto, isFirst
  98. }
  99. }
  100. if frequency.Duration == 3 {
  101. day := now.Day()
  102. if !utils.InArr(utils.IntToStr(day), frequency.Num) {
  103. return errors.New("非可提现日期"), realAmount, fee, isAuto, isFirst
  104. }
  105. }
  106. if withdrawSetting.WithdrawNumsLimit > 0 {
  107. var withdrawNums int64
  108. var startOfDay, endOfDay time.Time
  109. if frequency.Duration == 1 { //按天
  110. startOfDay = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
  111. endOfDay = startOfDay.Add(24 * time.Hour)
  112. }
  113. if frequency.Duration == 2 { //按周
  114. startOfDay = utils.GetStartOfWeek(now)
  115. endOfDay = startOfDay.Add(7 * 24 * time.Hour)
  116. }
  117. if frequency.Duration == 3 { //按月
  118. startOfDay = utils.GetFirstDateOfMonth(now)
  119. endOfDay = utils.GetLastDateOfMonth(now)
  120. }
  121. withdrawNums, err = db.Db.Where("create_at >= ?", startOfDay.Format("2006-01-02 15:04:05")).
  122. And("create_at < ?", endOfDay.Format("2006-01-02 15:04:05")).
  123. And("uid =?", user.Id).
  124. And("state != 3"). //失败不计入
  125. Count(&model.FinWithdrawApply{})
  126. if err != nil {
  127. return err, realAmount, fee, isAuto, isFirst
  128. }
  129. if int(withdrawNums) >= withdrawSetting.WithdrawNumsLimit {
  130. return errors.New("当前已无可提现次数"), realAmount, fee, isAuto, isFirst
  131. }
  132. }
  133. //9、计算手续费
  134. var feeSet md.WithdrawFeeSetStruct
  135. utils.Unserialize([]byte(withdrawSetting.WithdrawFeeSet), &feeSet)
  136. if feeSet.Value > 0 {
  137. feeSerValue := decimal.NewFromInt(int64(feeSet.Value))
  138. if feeSet.Kind == 2 { //固定比例
  139. feeSerValue = amountValue.Mul(feeSerValue.Div(decimal.NewFromInt(100)))
  140. fee = amountValue.Mul(feeSerValue.Div(decimal.NewFromInt(100))).String()
  141. }
  142. fee = feeSerValue.String()
  143. realAmount = amountValue.Sub(feeSerValue).String()
  144. }
  145. //10、判断是否为自动提现
  146. if withdrawSetting.IsAuto > 0 {
  147. autoAmountLimit, _ := decimal.NewFromString(withdrawSetting.IsAutoAmountLimit)
  148. if amountValue.LessThanOrEqual(autoAmountLimit) {
  149. isAuto = true
  150. }
  151. }
  152. if utils.StrToFloat64(realAmount) <= 0 {
  153. return errors.New("当前提现金额有误"), realAmount, fee, isAuto, isFirst
  154. }
  155. return
  156. }
  157. func GetWithdrawCondition(user *model.User, setting *model.FinWithdrawSetting, isFirst bool) md2.GetWithdrawConditionResp {
  158. resp := md2.GetWithdrawConditionResp{
  159. IsCanWithdraw: true,
  160. IsBindAlipay: false,
  161. IsBindWx: false,
  162. }
  163. // 1.判断是否需要实名
  164. switch setting.IsRealName {
  165. case 0:
  166. resp.IsNeedRealName = false
  167. case 1:
  168. resp.IsNeedRealName = true
  169. default:
  170. resp.IsNeedRealName = true
  171. }
  172. // 2.判断是否实名
  173. switch user.IsRealName {
  174. case 0:
  175. resp.IsRealName = false
  176. if resp.IsNeedRealName {
  177. // 2.1 需要实名但未实名
  178. resp.IsCanWithdraw = false
  179. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  180. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotRealName)
  181. }
  182. case 1:
  183. resp.IsRealName = true
  184. default:
  185. resp.IsRealName = false
  186. }
  187. // 3. 验证会员等级
  188. if setting.VipLevelLimit > 0 && setting.VipLevelLimit > user.Level {
  189. resp.IsCanWithdraw = false
  190. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  191. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotEnoughLevel)
  192. }
  193. //4、验证时段
  194. now := time.Now()
  195. if setting.WithdrawTimeInterval != "" {
  196. withdrawTimeInterval := strings.Split(setting.WithdrawTimeInterval, "-")
  197. // 定义要比较的时间格式
  198. layout := "15:04"
  199. // 解析给定的时间字符串
  200. start, _ := time.Parse(layout, withdrawTimeInterval[0])
  201. end, _ := time.Parse(layout, withdrawTimeInterval[1])
  202. // 设置为今天的日期
  203. start = time.Date(now.Year(), now.Month(), now.Day(), start.Hour(), start.Minute(), 0, 0, now.Location())
  204. end = time.Date(now.Year(), now.Month(), now.Day(), end.Hour(), end.Minute(), 0, 0, now.Location())
  205. // 如果结束时间小于开始时间,说明跨天了
  206. if end.Before(start) {
  207. if !(now.After(start) || now.Before(end)) {
  208. resp.IsCanWithdraw = false
  209. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  210. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotInTime)
  211. }
  212. } else { // 否则,在同一天内比较
  213. if !(now.After(start) && now.Before(end)) {
  214. resp.IsCanWithdraw = false
  215. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  216. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotInTime)
  217. }
  218. }
  219. }
  220. // 5. 首次提现判断
  221. if isFirst {
  222. var firstWithdrawSet md.FirstWithdrawSet
  223. utils.Unserialize([]byte(setting.FirstWithdrawSet), &firstWithdrawSet)
  224. if firstWithdrawSet.IsNeedRealName == 0 {
  225. resp.IsNeedRealName = false
  226. }
  227. }
  228. return resp
  229. }