package svc import ( "applet/app/db" "applet/app/e" md2 "applet/app/md" "applet/app/utils" "code.fnuoos.com/EggPlanet/egg_models.git/src/implement" "code.fnuoos.com/EggPlanet/egg_models.git/src/model" "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" "errors" "github.com/gin-gonic/gin" "github.com/shopspring/decimal" "math" "strings" "time" ) func CheckWithdraw(c *gin.Context, amount string) (err error, realAmount, fee string, isAuto, isFirst bool) { realAmount = amount user := GetUser(c) now := time.Now() amountValue, _ := decimal.NewFromString(amount) //1、查询 fin_withdraw_setting 提现设置表 finWithdrawSettingDb := implement.NewFinWithdrawSettingDb(db.Db) withdrawSetting, err := finWithdrawSettingDb.FinWithdrawSettingGetOne() if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } //2、判断是否为第一次提现 var isCompleteFirstWithdraw bool has, err := db.Db.Where("uid =?", user.Id).Get(&model.FinWithdrawApply{}) if err != nil { return } if !has { //第一次提现 isFirst = true var firstWithdrawSet md.FirstWithdrawSet utils.Unserialize([]byte(withdrawSetting.FrequencySet), &firstWithdrawSet) if firstWithdrawSet.IsNeedRealName == 0 && firstWithdrawSet.FirstWithdrawAmountLimit >= amount { isCompleteFirstWithdraw = true } } //2、判断“是否实名” if isCompleteFirstWithdraw && withdrawSetting.IsRealName == 1 && user.IsRealName != 1 { return errors.New("非实名用户不可提现"), realAmount, fee, isAuto, isFirst } //3、判断“提现金额” if isCompleteFirstWithdraw && utils.StrToFloat64(withdrawSetting.WithdrawAmountLimit) > 0 { withdrawAmountLimitValue, _ := decimal.NewFromString(withdrawSetting.WithdrawAmountLimit) if amountValue.LessThan(withdrawAmountLimitValue) { return errors.New("非可提现金额"), realAmount, fee, isAuto, isFirst } } //4、判断“提现倍数” if isCompleteFirstWithdraw && utils.StrToFloat64(withdrawSetting.WithdrawMultipleLimit) > 0 { result := utils.StrToFloat64(amount) / utils.StrToFloat64(withdrawSetting.WithdrawMultipleLimit) // 检查结果是否非常接近一个整数 roundedResult := math.Round(result) if !(math.Abs(roundedResult-result) < 1e-9) { return errors.New("非可提现倍数"), realAmount, fee, isAuto, isFirst } } //5、验证会员等级 if isCompleteFirstWithdraw && withdrawSetting.VipLevelLimit > 0 && withdrawSetting.VipLevelLimit > user.Level { return errors.New("非可提现会员等级"), realAmount, fee, isAuto, isFirst } //6、 验证小数点 if isCompleteFirstWithdraw && withdrawSetting.IsSupportDecimalPoint == 0 && strings.Contains(amount, ".") { return errors.New("不支持的提现金额"), realAmount, fee, isAuto, isFirst } //7、验证时段 if withdrawSetting.WithdrawTimeInterval != "" { withdrawTimeInterval := strings.Split(withdrawSetting.WithdrawTimeInterval, "-") // 定义要比较的时间格式 layout := "15:04" // 解析给定的时间字符串 start, _ := time.Parse(layout, withdrawTimeInterval[0]) end, _ := time.Parse(layout, withdrawTimeInterval[1]) // 设置为今天的日期 start = time.Date(now.Year(), now.Month(), now.Day(), start.Hour(), start.Minute(), 0, 0, now.Location()) end = time.Date(now.Year(), now.Month(), now.Day(), end.Hour(), end.Minute(), 0, 0, now.Location()) // 如果结束时间小于开始时间,说明跨天了 if end.Before(start) { if !(now.After(start) || now.Before(end)) { return errors.New("非可提现时间段"), realAmount, fee, isAuto, isFirst } } else { // 否则,在同一天内比较 if !(now.After(start) && now.Before(end)) { return errors.New("非可提现时间段"), realAmount, fee, isAuto, isFirst } } } //8、验证“提现频率” var frequency md.WithdrawFrequencySettingStruct utils.Unserialize([]byte(withdrawSetting.FrequencySet), &frequency) if frequency.Duration == 2 { day := now.Weekday() if !utils.InArr(utils.IntToStr(int(day)), frequency.Num) { return errors.New("非可提现日期"), realAmount, fee, isAuto, isFirst } } if frequency.Duration == 3 { day := now.Day() if !utils.InArr(utils.IntToStr(day), frequency.Num) { return errors.New("非可提现日期"), realAmount, fee, isAuto, isFirst } } if withdrawSetting.WithdrawNumsLimit > 0 { var withdrawNums int64 var startOfDay, endOfDay time.Time if frequency.Duration == 1 { //按天 startOfDay = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) endOfDay = startOfDay.Add(24 * time.Hour) } if frequency.Duration == 2 { //按周 startOfDay = utils.GetStartOfWeek(now) endOfDay = startOfDay.Add(7 * 24 * time.Hour) } if frequency.Duration == 3 { //按月 startOfDay = utils.GetFirstDateOfMonth(now) endOfDay = utils.GetLastDateOfMonth(now) } withdrawNums, err = db.Db.Where("create_at >= ?", startOfDay.Format("2006-01-02 15:04:05")). And("create_at < ?", endOfDay.Format("2006-01-02 15:04:05")). And("uid =?", user.Id). And("state != 3"). //失败不计入 Count(&model.FinWithdrawApply{}) if err != nil { return err, realAmount, fee, isAuto, isFirst } if int(withdrawNums) >= withdrawSetting.WithdrawNumsLimit { return errors.New("当前已无可提现次数"), realAmount, fee, isAuto, isFirst } } //9、计算手续费 var feeSet md.WithdrawFeeSetStruct utils.Unserialize([]byte(withdrawSetting.WithdrawFeeSet), &feeSet) if feeSet.Value > 0 { feeSerValue := decimal.NewFromInt(int64(feeSet.Value)) if feeSet.Kind == 2 { //固定比例 feeSerValue = amountValue.Mul(feeSerValue.Div(decimal.NewFromInt(100))) fee = amountValue.Mul(feeSerValue.Div(decimal.NewFromInt(100))).String() } fee = feeSerValue.String() realAmount = amountValue.Sub(feeSerValue).String() } //10、判断是否为自动提现 if withdrawSetting.IsAuto > 0 { autoAmountLimit, _ := decimal.NewFromString(withdrawSetting.IsAutoAmountLimit) if amountValue.LessThanOrEqual(autoAmountLimit) { isAuto = true } } if utils.StrToFloat64(realAmount) <= 0 { return errors.New("当前提现金额有误"), realAmount, fee, isAuto, isFirst } return } func GetWithdrawCondition(user *model.User, setting *model.FinWithdrawSetting, isFirst bool) md2.GetWithdrawConditionResp { resp := md2.GetWithdrawConditionResp{ IsCanWithdraw: true, IsBindAlipay: false, IsBindWx: false, } // 1.判断是否需要实名 switch setting.IsRealName { case 0: resp.IsNeedRealName = false case 1: resp.IsNeedRealName = true default: resp.IsNeedRealName = true } // 2.判断是否实名 switch user.IsRealName { case 0: resp.IsRealName = false if resp.IsNeedRealName { // 2.1 需要实名但未实名 resp.IsCanWithdraw = false resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotRealName) } case 1: resp.IsRealName = true default: resp.IsRealName = false } // 3. 验证会员等级 if setting.VipLevelLimit > 0 && setting.VipLevelLimit > user.Level { resp.IsCanWithdraw = false resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotEnoughLevel) } //4、验证时段 now := time.Now() if setting.WithdrawTimeInterval != "" { withdrawTimeInterval := strings.Split(setting.WithdrawTimeInterval, "-") // 定义要比较的时间格式 layout := "15:04" // 解析给定的时间字符串 start, _ := time.Parse(layout, withdrawTimeInterval[0]) end, _ := time.Parse(layout, withdrawTimeInterval[1]) // 设置为今天的日期 start = time.Date(now.Year(), now.Month(), now.Day(), start.Hour(), start.Minute(), 0, 0, now.Location()) end = time.Date(now.Year(), now.Month(), now.Day(), end.Hour(), end.Minute(), 0, 0, now.Location()) // 如果结束时间小于开始时间,说明跨天了 if end.Before(start) { if !(now.After(start) || now.Before(end)) { resp.IsCanWithdraw = false resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotInTime) } } else { // 否则,在同一天内比较 if !(now.After(start) && now.Before(end)) { resp.IsCanWithdraw = false resp.NotWithdrawReason = enum.FinWithdrawApplyWithdrawConditionDissatisfyKind. String(enum.FinWithdrawApplyWithdrawConditionDissatisfyKindNotInTime) } } } // 5. 首次提现判断 if isFirst { var firstWithdrawSet md.FirstWithdrawSet utils.Unserialize([]byte(setting.FirstWithdrawSet), &firstWithdrawSet) if firstWithdrawSet.IsNeedRealName == 0 { resp.IsNeedRealName = false } } return resp }