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

312 lines
11 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 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. now := time.Now()
  167. // 1.判断是否需要实名
  168. switch setting.IsRealName {
  169. case 0:
  170. resp.IsNeedRealName = false
  171. case 1:
  172. resp.IsNeedRealName = true
  173. default:
  174. resp.IsNeedRealName = true
  175. }
  176. // 2.判断是否实名
  177. switch user.IsRealName {
  178. case 0:
  179. resp.IsRealName = false
  180. if resp.IsNeedRealName {
  181. // 2.1 需要实名但未实名
  182. resp.IsCanWithdraw = false
  183. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  184. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotRealName)
  185. }
  186. case 1:
  187. resp.IsRealName = true
  188. default:
  189. resp.IsRealName = false
  190. }
  191. // 3. 首次提现判断
  192. if isFirst {
  193. resp.IsFirst = true
  194. resp.IsCanWithdraw = true
  195. resp.NotWithdrawReason = ""
  196. var firstWithdrawSet md.FirstWithdrawSet
  197. utils.Unserialize([]byte(setting.FirstWithdrawSet), &firstWithdrawSet)
  198. resp.FirstNeedRealName = func(firstWithdrawSetIsNeedRealName int) bool {
  199. if firstWithdrawSet.IsNeedRealName == 1 {
  200. return true
  201. }
  202. return false
  203. }(firstWithdrawSet.IsNeedRealName)
  204. resp.FirstWithdrawAmountLimit = firstWithdrawSet.FirstWithdrawAmountLimit
  205. } else {
  206. // 4. 验证会员等级
  207. if setting.VipLevelLimit > 0 && setting.VipLevelLimit > user.Level {
  208. resp.IsCanWithdraw = false
  209. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  210. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotEnoughLevel)
  211. }
  212. //5、验证“提现频率”
  213. var frequency md.WithdrawFrequencySettingStruct
  214. utils.Unserialize([]byte(setting.FrequencySet), &frequency)
  215. if frequency.Duration == 2 {
  216. day := now.Weekday()
  217. if !utils.InArr(utils.IntToStr(int(day)), frequency.Num) {
  218. resp.IsCanWithdraw = false
  219. resp.NotWithdrawReason = "非可提现日期"
  220. }
  221. }
  222. if frequency.Duration == 3 {
  223. day := now.Day()
  224. if !utils.InArr(utils.IntToStr(day), frequency.Num) {
  225. resp.IsCanWithdraw = false
  226. resp.NotWithdrawReason = "非可提现日期"
  227. }
  228. }
  229. if setting.WithdrawNumsLimit > 0 {
  230. var withdrawNums int64
  231. var startOfDay, endOfDay time.Time
  232. if frequency.Duration == 1 { //按天
  233. startOfDay = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
  234. endOfDay = startOfDay.Add(24 * time.Hour)
  235. }
  236. if frequency.Duration == 2 { //按周
  237. startOfDay = utils.GetStartOfWeek(now)
  238. endOfDay = startOfDay.Add(7 * 24 * time.Hour)
  239. }
  240. if frequency.Duration == 3 { //按月
  241. startOfDay = utils.GetFirstDateOfMonth(now)
  242. endOfDay = utils.GetLastDateOfMonth(now)
  243. }
  244. withdrawNums, err := db.Db.Where("create_at >= ?", startOfDay.Format("2006-01-02 15:04:05")).
  245. And("create_at < ?", endOfDay.Format("2006-01-02 15:04:05")).
  246. And("uid =?", user.Id).
  247. And("state != 3"). //失败不计入
  248. Count(&model.FinWithdrawApply{})
  249. if err != nil {
  250. resp.IsCanWithdraw = false
  251. resp.NotWithdrawReason = err.Error()
  252. }
  253. if int(withdrawNums) >= setting.WithdrawNumsLimit {
  254. resp.IsCanWithdraw = false
  255. resp.NotWithdrawReason = "当前已无可提现次数"
  256. }
  257. }
  258. }
  259. //6、验证时段
  260. if setting.WithdrawTimeInterval != "" {
  261. withdrawTimeInterval := strings.Split(setting.WithdrawTimeInterval, "-")
  262. // 定义要比较的时间格式
  263. layout := "15:04"
  264. // 解析给定的时间字符串
  265. start, _ := time.Parse(layout, withdrawTimeInterval[0])
  266. end, _ := time.Parse(layout, withdrawTimeInterval[1])
  267. // 设置为今天的日期
  268. start = time.Date(now.Year(), now.Month(), now.Day(), start.Hour(), start.Minute(), 0, 0, now.Location())
  269. end = time.Date(now.Year(), now.Month(), now.Day(), end.Hour(), end.Minute(), 0, 0, now.Location())
  270. // 如果结束时间小于开始时间,说明跨天了
  271. if end.Before(start) {
  272. if !(now.After(start) || now.Before(end)) {
  273. resp.IsCanWithdraw = false
  274. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  275. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotInTime)
  276. }
  277. } else { // 否则,在同一天内比较
  278. if !(now.After(start) && now.Before(end)) {
  279. resp.IsCanWithdraw = false
  280. resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind.
  281. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotInTime)
  282. }
  283. }
  284. }
  285. return resp
  286. }