蛋蛋星球-客户端
選択できるのは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. }