蛋蛋星球-客户端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

svc_withdraw_apply.go 10 KiB

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