diff --git a/app/db/db_master.go b/app/db/db_master.go new file mode 100644 index 0000000..0d94e1a --- /dev/null +++ b/app/db/db_master.go @@ -0,0 +1,41 @@ +package db + +import ( + "applet/app/db/model" + "time" + "xorm.io/xorm" +) + +type MasterDb struct { + Db *xorm.Engine `json:"db"` +} + +func (masterDb *MasterDb) Set() { // set方法 + masterDb.Db = ZhimengDb +} + +func (masterDb *MasterDb) GetMaster(mid string) *model.Master { + var data model.Master + get, err := masterDb.Db.Where("master_id=?", mid).Get(&data) + if get == false || err != nil { + data = model.Master{MasterId: mid, CreateTime: time.Now(), UpdateTime: time.Now(), FormWay: "api"} + masterDb.Db.InsertOne(&data) + } + return &data +} +func (masterDb *MasterDb) GetMasterId(id int) *model.Master { + var data model.Master + get, err := masterDb.Db.Where("id=?", id).Get(&data) + if get == false || err != nil { + return nil + } + return &data +} + +func (masterDb *MasterDb) MasterUpdate(data *model.Master) bool { + get, err := masterDb.Db.Where("id=?", data.Id).Update(data) + if get == 0 || err != nil { + return false + } + return true +} diff --git a/app/db/db_master_amount.go b/app/db/db_master_amount.go new file mode 100644 index 0000000..e5203fc --- /dev/null +++ b/app/db/db_master_amount.go @@ -0,0 +1,71 @@ +package db + +import ( + "applet/app/db/model" + "applet/app/utils" + "time" + "xorm.io/xorm" +) + +type MasterAmountDb struct { + Db *xorm.Engine `json:"db"` +} + +func (masterAmountDb *MasterAmountDb) Set() { // set方法 + masterAmountDb.Db = ZhimengDb +} + +func (masterAmountDb *MasterAmountDb) GetMasterAmount(id, types string) *model.MasterAmount { + var data model.MasterAmount + get, err := masterAmountDb.Db.Where("uid=? and type=?", id, types).Get(&data) + if get == false || err != nil { + data = model.MasterAmount{Uid: id, Type: types, UpdateTime: time.Now()} + masterAmountDb.Db.InsertOne(&data) + } + return &data +} +func (masterAmountDb *MasterAmountDb) GetMasterAmountList(args map[string]string) *[]model.MasterAmount { + var data = make([]model.MasterAmount, 0) + size := utils.StrToInt(args["size"]) + offet := (utils.StrToInt(args["p"]) - 1) * size + sess := masterAmountDb.Db.Where("last_month_amount>0") + sess.Limit(size, offet).OrderBy("id desc").Find(&data) + return &data +} +func (masterAmountDb *MasterAmountDb) GetMasterAmountByListId(id string) *model.MasterAmount { + var data model.MasterAmount + get, err := masterAmountDb.Db.Where("id=?", id).Get(&data) + if get == false || err != nil { + return nil + } + return &data +} +func (masterAmountDb *MasterAmountDb) MasterAmountUpdate(id int, data *model.MasterAmount) bool { + get, err := masterAmountDb.Db.Where("id=?", id).Update(data) + if get == 0 || err != nil { + return false + } + return true +} +func (masterAmountDb *MasterAmountDb) MasterAmountInsert(data *model.MasterAmount) bool { + get, err := masterAmountDb.Db.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} +func GetMasterAmountByListIdWithSess(sess *xorm.Session, id string) *model.MasterAmount { + var data model.MasterAmount + get, err := sess.Where("id=?", id).Get(&data) + if get == false || err != nil { + return nil + } + return &data +} +func MasterAmountUpdateWithSess(sess *xorm.Session, id int, data *model.MasterAmount) bool { + get, err := sess.Where("id=?", id).Update(data) + if get == 0 || err != nil { + return false + } + return true +} diff --git a/app/db/db_master_amount_list.go b/app/db/db_master_amount_list.go new file mode 100644 index 0000000..7a807b7 --- /dev/null +++ b/app/db/db_master_amount_list.go @@ -0,0 +1,36 @@ +package db + +import ( + "applet/app/db/model" + "xorm.io/xorm" +) + +type MasterAmountFlowDb struct { + Db *xorm.Engine `json:"db"` +} + +func (masterAmountFlowDb *MasterAmountFlowDb) Set() { // set方法 + masterAmountFlowDb.Db = ZhimengDb +} + +func (masterAmountFlowDb *MasterAmountFlowDb) MasterAmountListUpdate(id int, data *model.MasterAmountFlow) bool { + get, err := masterAmountFlowDb.Db.Where("id=?", id).Update(data) + if get == 0 || err != nil { + return false + } + return true +} +func (masterAmountFlowDb *MasterAmountFlowDb) MasterAmountFlowInsert(data *model.MasterAmountFlow) bool { + get, err := masterAmountFlowDb.Db.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} +func MasterAmountFlowInsertWithSess(sess *xorm.Session, data *model.MasterAmountFlow) bool { + get, err := sess.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} diff --git a/app/db/db_master_last_month_amount_list.go b/app/db/db_master_last_month_amount_list.go new file mode 100644 index 0000000..93b1c27 --- /dev/null +++ b/app/db/db_master_last_month_amount_list.go @@ -0,0 +1,36 @@ +package db + +import ( + "applet/app/db/model" + "xorm.io/xorm" +) + +type MasterLastMonthAmountFlowDb struct { + Db *xorm.Engine `json:"db"` +} + +func (masterLastMonthAmountFlowDb *MasterLastMonthAmountFlowDb) Set() { // set方法 + masterLastMonthAmountFlowDb.Db = ZhimengDb +} + +func (masterLastMonthAmountFlowDb *MasterLastMonthAmountFlowDb) MasterLastMonthAmountListUpdate(id int, data *model.MasterLastMonthAmountFlow) bool { + get, err := masterLastMonthAmountFlowDb.Db.Where("id=?", id).Update(data) + if get == 0 || err != nil { + return false + } + return true +} +func (masterLastMonthAmountFlowDb *MasterLastMonthAmountFlowDb) MasterLastMonthAmountFlowInsert(data *model.MasterLastMonthAmountFlow) bool { + get, err := masterLastMonthAmountFlowDb.Db.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} +func MasterLastMonthAmountFlowInsertWithSess(sess *xorm.Session, data *model.MasterLastMonthAmountFlow) bool { + get, err := sess.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} diff --git a/app/db/db_master_list_cfg.go b/app/db/db_master_list_cfg.go index 2ab67ee..ce4ced2 100644 --- a/app/db/db_master_list_cfg.go +++ b/app/db/db_master_list_cfg.go @@ -19,21 +19,21 @@ func (masterListCfgDb *MasterListCfgDb) Set() { // set方法 func (masterListCfgDb *MasterListCfgDb) MasterListCfgGetAll() (*[]model.MasterListCfg, error) { var cfgList []model.MasterListCfg - if err := Db.Cols("k,v,memo").Find(&cfgList); err != nil { + if err := masterListCfgDb.Db.Cols("k,v,memo").Find(&cfgList); err != nil { return nil, logx.Error(err) } return &cfgList, nil } func (masterListCfgDb *MasterListCfgDb) MasterListCfgGetCron() (*[]model.MasterListCfg, error) { var cfgList []model.MasterListCfg - if err := Db.Where("`k` LIKE 'zhimeng_cron\\_%' AND v != ''").Cols("k,v,memo").Find(&cfgList); err != nil { + if err := masterListCfgDb.Db.Where("`k` LIKE 'zhimeng_cron\\_%' AND v != ''").Cols("k,v,memo").Find(&cfgList); err != nil { return nil, logx.Error(err) } return &cfgList, nil } func (masterListCfgDb *MasterListCfgDb) MasterListCfgGetOneNoDataNoErr(key string) (*model.MasterListCfg, error) { var cfgList model.MasterListCfg - has, err := Db.Where("`k`=?", key).Get(&cfgList) + has, err := masterListCfgDb.Db.Where("`k`=?", key).Get(&cfgList) if err != nil { return nil, logx.Error(err) } @@ -45,22 +45,32 @@ func (masterListCfgDb *MasterListCfgDb) MasterListCfgGetOneNoDataNoErr(key strin func (masterListCfgDb *MasterListCfgDb) MasterListCfgGetOne(uid, key string) (*model.MasterListCfg, error) { var cfgList model.MasterListCfg - if has, err := Db.Where("`k`=? and uid=?", key, uid).Get(&cfgList); err != nil || has == false { + has, err := masterListCfgDb.Db.Where("`k`=? and uid=?", key, uid).Get(&cfgList) + if err != nil { return nil, logx.Error(err) } + if has == false { + cfgList = model.MasterListCfg{Uid: uid, K: key} + masterListCfgDb.Db.InsertOne(&cfgList) + } return &cfgList, nil } func (masterListCfgDb *MasterListCfgDb) MasterListCfgGetOneData(uid, key string) string { var cfgList model.MasterListCfg - if has, err := Db.Where("`k`=? and uid=?", key, uid).Get(&cfgList); err != nil || has == false { + has, err := masterListCfgDb.Db.Where("`k`=? and uid=?", key, uid).Get(&cfgList) + if err != nil { return "" } + if has == false { + cfgList = model.MasterListCfg{Uid: uid, K: key} + masterListCfgDb.Db.InsertOne(&cfgList) + } return cfgList.V } func (masterListCfgDb *MasterListCfgDb) MasterListCfgInsert(uid, key, val, memo string) bool { cfg := model.MasterListCfg{Uid: uid, K: key, V: val, Memo: memo} - _, err := Db.InsertOne(&cfg) + _, err := masterListCfgDb.Db.InsertOne(&cfg) if err != nil { logx.Error(err) return false @@ -69,8 +79,9 @@ func (masterListCfgDb *MasterListCfgDb) MasterListCfgInsert(uid, key, val, memo } func (masterListCfgDb *MasterListCfgDb) MasterListCfgUpdate(uid, key, val string) bool { + masterListCfgDb.MasterListCfgGetOneData(uid, key) cfg := model.MasterListCfg{K: key, V: val} - _, err := Db.Where("`k`=? and uid=?", key, uid).Cols("val").Update(&cfg) + _, err := masterListCfgDb.Db.Where("`k`=? and uid=?", key, uid).Cols("v").Update(&cfg) if err != nil { logx.Error(err) return false diff --git a/app/db/db_master_withdrawal_flow.go b/app/db/db_master_withdrawal_flow.go new file mode 100644 index 0000000..252aed5 --- /dev/null +++ b/app/db/db_master_withdrawal_flow.go @@ -0,0 +1,108 @@ +package db + +import ( + "applet/app/db/model" + "applet/app/utils" + "xorm.io/xorm" +) + +type MasterWithdrawalFlowDb struct { + Db *xorm.Engine `json:"db"` +} + +func (masterWithdrawalFlowDb *MasterWithdrawalFlowDb) Set() { // set方法 + masterWithdrawalFlowDb.Db = ZhimengDb +} + +func (masterWithdrawalFlowDb *MasterWithdrawalFlowDb) GetWithdrawalFlowListWithTotal(id string, args map[string]string) (*[]model.MasterWithdrawalFlow, int64) { + var data []model.MasterWithdrawalFlow + sess := masterWithdrawalFlowDb.Db.Where("uid=?", id) + if args["start_time"] != "" { + sess = sess.And("time>=?", args["start_time"]) + } + if args["end_time"] != "" { + sess = sess.And("time<=?", args["end_time"]) + } + if args["check_start_time"] != "" { + sess = sess.And("check_time>=?", args["check_start_time"]) + } + if args["check_end_time"] != "" { + sess = sess.And("check_time<=?", args["check_end_time"]) + } + if args["status"] != "" { + sess = sess.And("status=?", args["status"]) + } + if args["alipay"] != "" { + sess = sess.And("alipay LIKE ?", "%"+args["alipay"]+"%") + } + p := utils.StrToInt(args["p"]) + size := utils.StrToInt(args["size"]) + offet := (p - 1) * size + total, err := sess.Limit(size, offet).OrderBy("time desc,id desc").FindAndCount(&data) + if err != nil { + return nil, total + } + return &data, total +} +func (masterWithdrawalFlowDb *MasterWithdrawalFlowDb) GetWithdrawalFlowList(id string, args map[string]string) *[]model.MasterWithdrawalFlow { + var data []model.MasterWithdrawalFlow + sess := masterWithdrawalFlowDb.Db.Where("uid=?", id) + if args["start_time"] != "" { + sess = sess.And("time>=?", args["start_time"]) + } + if args["end_time"] != "" { + sess = sess.And("time<=?", args["end_time"]) + } + if args["check_start_time"] != "" { + sess = sess.And("check_time>=?", args["check_start_time"]) + } + if args["check_end_time"] != "" { + sess = sess.And("check_time<=?", args["check_end_time"]) + } + if args["status"] != "" { + sess = sess.And("status=?", args["status"]) + } + if args["alipay"] != "" { + sess = sess.And("alipay LIKE ?", "%"+args["alipay"]+"%") + } + p := utils.StrToInt(args["p"]) + size := utils.StrToInt(args["size"]) + offet := (p - 1) * size + err := sess.Limit(size, offet).OrderBy("time desc,id desc").Find(&data) + if err != nil { + return nil + } + return &data +} + +func (masterWithdrawalFlowDb *MasterWithdrawalFlowDb) MasterWithdrawalFlowInsert(data *model.MasterWithdrawalFlow) bool { + get, err := masterWithdrawalFlowDb.Db.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} + +func (masterWithdrawalFlowDb *MasterWithdrawalFlowDb) MasterWithdrawalFlowInsertUpdate(data *model.MasterWithdrawalFlow) bool { + get, err := masterWithdrawalFlowDb.Db.Where("id=?", data.Id).Update(data) + if get == 0 || err != nil { + return false + } + return true +} +func MasterWithdrawalFlowInsertWithSess(sess *xorm.Session, data *model.MasterWithdrawalFlow) bool { + get, err := sess.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} +func (masterWithdrawalFlowDb *MasterWithdrawalFlowDb) MasterWithdrawalFlowById(id string) *model.MasterWithdrawalFlow { + var data model.MasterWithdrawalFlow + get, err := masterWithdrawalFlowDb.Db.Where("id=?", id).Get(&data) + if get == false || err != nil { + return nil + } + return &data + +} diff --git a/app/db/db_playlet_sale_order.go b/app/db/db_playlet_sale_order.go index f999eec..f9226da 100644 --- a/app/db/db_playlet_sale_order.go +++ b/app/db/db_playlet_sale_order.go @@ -3,6 +3,8 @@ package db import ( "applet/app/db/model" "applet/app/utils" + "fmt" + "time" "xorm.io/xorm" ) @@ -38,7 +40,19 @@ func (playletSaleOrderDb *PlayletSaleOrderDb) PlayletVideoOrderInsert(data *mode } return true } - +func (playletSaleOrderDb *PlayletSaleOrderDb) PlayletVideoOrderSum(mid, status, timeType string) float64 { + sess := playletSaleOrderDb.Db.Where("uid=?", mid) + if status != "" { + sess = sess.And("status=?", status) + } + if timeType != "" { + timeRange := utils.GetTimeRange(timeType) + sess = sess.And("create_time>=?", time.Unix(timeRange["start"], 0).Format("2006-01-02 15:04:05")) + sess = sess.And("create_time=?", args["start_time"]) } if args["end_time"] != "" { - sess = sess.And("update_time>=?", args["end_time"]) + sess = sess.And("update_time<=?", args["end_time"]) + } + + if args["to_settle_time"] != "" { + sess = sess.And("create_time=?", args["start_time"]) + } + if args["end_time"] != "" { + sess = sess.And("create_time>=?", args["end_time"]) + } + sess = commWhere(sess, args) + sort := "update_time desc,id desc" + if args["sort"] != "" { + sort = args["sort"] + } + count, err := sess.Limit(size, offet).OrderBy(sort).FindAndCount(&data) + if count == 0 || err != nil { + return nil, count + } + return &data, count +} +func (playletSaleOrderDb *PlayletSaleOrderDb) GetPlayletVideoOrderListWithCreateTime(args map[string]string) *[]model.PlayletSaleOrder { + /*** + p 页数 + size 个数 + start_time 开始时间 + end_time 结束时间 + ord_type 订单类型 + video_type 视频类型 + status 订单状态 + settle_status 结算状态 + oid 订单号 + sort 排序 + */ + var data = make([]model.PlayletSaleOrder, 0) + size := utils.StrToInt(args["size"]) + offet := (utils.StrToInt(args["p"]) - 1) * size + sess := playletSaleOrderDb.Db.Where("1=1") + if args["start_time"] != "" { + sess = sess.And("create_time>=?", args["start_time"]) + } + if args["end_time"] != "" { + sess = sess.And("create_time>=?", args["end_time"]) + } + sess = commWhere(sess, args) + sort := "update_time desc,id desc" + if args["sort"] != "" { + sort = args["sort"] + } + err := sess.Limit(size, offet).OrderBy(sort).Find(&data) + if err != nil { + return nil + } + return &data +} +func commWhere(sess *xorm.Session, args map[string]string) *xorm.Session { + if args["mid"] != "" { + sess = sess.And("uid=?", args["mid"]) + } + + if args["oid"] != "" { + sess = sess.And("oid LIKE ? or custom_oid LIKE ?", "%"+args["oid"]+"%", "%"+args["oid"]+"%") + } + if args["sub_uid"] != "" { + sess = sess.And("sub_uid=?", args["sub_uid"]) } if args["ord_type"] != "" { sess = sess.And("ord_type=?", args["ord_type"]) @@ -65,6 +179,15 @@ func (playletSaleOrderDb *PlayletSaleOrderDb) GetPlayletVideoOrderList(args map[ if args["video_type"] != "" { sess = sess.And("video_type=?", args["video_type"]) } - sess.Limit(size, offet).OrderBy("update_time desc,id desc").Find(&data) - return data + if args["status"] != "" { + sess = sess.And("status=?", args["status"]) + } + if args["settle_status"] != "" { + if args["settle_status"] == "未结算" { + sess = sess.And("settle_at=?", "0") + } else { + sess = sess.And("settle_at>?", "0") + } + } + return sess } diff --git a/app/db/db_sys_cfg.go b/app/db/db_sys_cfg.go index 4982933..4a768af 100644 --- a/app/db/db_sys_cfg.go +++ b/app/db/db_sys_cfg.go @@ -19,21 +19,21 @@ func (sysCfgDb *SysCfgDb) Set() { // set方法 func (sysCfgDb *SysCfgDb) SysCfgGetAll() (*[]model.SysCfg, error) { var cfgList []model.SysCfg - if err := Db.Cols("k,v,memo").Find(&cfgList); err != nil { + if err := sysCfgDb.Db.Cols("k,v,memo").Find(&cfgList); err != nil { return nil, logx.Error(err) } return &cfgList, nil } func (sysCfgDb *SysCfgDb) SysCfgGetCron() (*[]model.SysCfg, error) { var cfgList []model.SysCfg - if err := Db.Where("`k` LIKE 'zhimeng_cron\\_%' AND v != ''").Cols("k,v,memo").Find(&cfgList); err != nil { + if err := sysCfgDb.Db.Where("`k` LIKE 'zhimeng_cron\\_%' AND v != ''").Cols("k,v,memo").Find(&cfgList); err != nil { return nil, logx.Error(err) } return &cfgList, nil } func (sysCfgDb *SysCfgDb) SysCfgGetOneNoDataNoErr(key string) (*model.SysCfg, error) { var cfgList model.SysCfg - has, err := Db.Where("`k`=?", key).Get(&cfgList) + has, err := sysCfgDb.Db.Where("`k`=?", key).Get(&cfgList) if err != nil { return nil, logx.Error(err) } @@ -45,14 +45,14 @@ func (sysCfgDb *SysCfgDb) SysCfgGetOneNoDataNoErr(key string) (*model.SysCfg, er func (sysCfgDb *SysCfgDb) SysCfgGetOne(key string) (*model.SysCfg, error) { var cfgList model.SysCfg - if has, err := Db.Where("`k`=?", key).Get(&cfgList); err != nil || has == false { + if has, err := sysCfgDb.Db.Where("`k`=?", key).Get(&cfgList); err != nil || has == false { return nil, logx.Error(err) } return &cfgList, nil } func (sysCfgDb *SysCfgDb) SysCfgGetOneData(key string) string { var cfgList model.SysCfg - if has, err := Db.Where("`k`=?", key).Get(&cfgList); err != nil || has == false { + if has, err := sysCfgDb.Db.Where("`k`=?", key).Get(&cfgList); err != nil || has == false { return "" } return cfgList.V @@ -60,7 +60,7 @@ func (sysCfgDb *SysCfgDb) SysCfgGetOneData(key string) string { func (sysCfgDb *SysCfgDb) SysCfgInsert(key, val, memo string) bool { cfg := model.SysCfg{K: key, V: val, Memo: memo} - _, err := Db.InsertOne(&cfg) + _, err := sysCfgDb.Db.InsertOne(&cfg) if err != nil { logx.Error(err) return false diff --git a/app/db/model/master.go b/app/db/model/master.go new file mode 100644 index 0000000..e27acfb --- /dev/null +++ b/app/db/model/master.go @@ -0,0 +1,21 @@ +package model + +import ( + "time" +) + +type Master struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + MasterId string `json:"master_id" xorm:"VARCHAR(255)"` + Phone string `json:"phone" xorm:"VARCHAR(255)"` + Password string `json:"password" xorm:"VARCHAR(255)"` + CreateTime time.Time `json:"create_time" xorm:"DATETIME"` + IsAgent int `json:"is_agent" xorm:"comment('是否代理') INT(1)"` + FormWay string `json:"form_way" xorm:"VARCHAR(255)"` + ZyId string `json:"zy_id" xorm:"VARCHAR(255)"` + MasterName string `json:"master_name" xorm:"VARCHAR(255)"` + UpdateTime time.Time `json:"update_time" xorm:"DATETIME"` + Alipay string `json:"alipay" xorm:"VARCHAR(255)"` + AlipayName string `json:"alipay_name" xorm:"VARCHAR(255)"` + ExtendUid string `json:"extend_uid" xorm:"VARCHAR(255)"` +} diff --git a/app/db/model/master_amount.go b/app/db/model/master_amount.go new file mode 100644 index 0000000..9a276c8 --- /dev/null +++ b/app/db/model/master_amount.go @@ -0,0 +1,16 @@ +package model + +import ( + "time" +) + +type MasterAmount struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + Uid string `json:"uid" xorm:"comment('master表的id') unique VARCHAR(255)"` + Amount string `json:"amount" xorm:"default 0.00 DECIMAL(20,2)"` + Type string `json:"type" xorm:"VARCHAR(255)"` + UpdateTime time.Time `json:"update_time" xorm:"DATETIME"` + LastMonthAmount string `json:"last_month_amount" xorm:"DECIMAL(20,2)"` + MonthAmount string `json:"month_amount" xorm:"DECIMAL(20,2)"` + ChangeTime time.Time `json:"change_time" xorm:"comment('标记本月是否把预估结算佣金转换') DATETIME"` +} diff --git a/app/db/model/master_amount_flow.go b/app/db/model/master_amount_flow.go new file mode 100644 index 0000000..5f31417 --- /dev/null +++ b/app/db/model/master_amount_flow.go @@ -0,0 +1,20 @@ +package model + +import ( + "time" +) + +type MasterAmountFlow struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + Uid string `json:"uid" xorm:"VARCHAR(255)"` + Time time.Time `json:"time" xorm:"DATETIME"` + BeforeAmount string `json:"before_amount" xorm:"default 0.00 DECIMAL(20,2)"` + Amount string `json:"amount" xorm:"default 0.00 DECIMAL(20,2)"` + AfterAmount string `json:"after_amount" xorm:"default 0.00 DECIMAL(20,2)"` + Platform string `json:"platform" xorm:"VARCHAR(255)"` + Oid string `json:"oid" xorm:"VARCHAR(255)"` + Title string `json:"title" xorm:"VARCHAR(255)"` + FlowType string `json:"flow_type" xorm:"VARCHAR(255)"` + IncomeType int `json:"income_type" xorm:"default 0 INT(1)"` + ExtendUid string `json:"extend_uid" xorm:"VARCHAR(255)"` +} diff --git a/app/db/model/master_last_month_amount_flow.go b/app/db/model/master_last_month_amount_flow.go new file mode 100644 index 0000000..1da24d8 --- /dev/null +++ b/app/db/model/master_last_month_amount_flow.go @@ -0,0 +1,20 @@ +package model + +import ( + "time" +) + +type MasterLastMonthAmountFlow struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + Uid string `json:"uid" xorm:"VARCHAR(255)"` + Time time.Time `json:"time" xorm:"DATETIME"` + BeforeAmount string `json:"before_amount" xorm:"default 0.00 DECIMAL(20,2)"` + Amount string `json:"amount" xorm:"default 0.00 DECIMAL(20,2)"` + AfterAmount string `json:"after_amount" xorm:"default 0.00 DECIMAL(20,2)"` + Platform string `json:"platform" xorm:"VARCHAR(255)"` + Oid string `json:"oid" xorm:"VARCHAR(255)"` + Title string `json:"title" xorm:"VARCHAR(255)"` + FlowType string `json:"flow_type" xorm:"VARCHAR(255)"` + IncomeType int `json:"income_type" xorm:"default 0 INT(1)"` + ExtendUid string `json:"extend_uid" xorm:"VARCHAR(255)"` +} diff --git a/app/db/model/master_list_cfg.go b/app/db/model/master_list_cfg.go index 8511817..34d4f7e 100644 --- a/app/db/model/master_list_cfg.go +++ b/app/db/model/master_list_cfg.go @@ -1,8 +1,8 @@ package model type MasterListCfg struct { - K string `json:"k" xorm:"not null pk comment('键') VARCHAR(127)"` - V string `json:"v" xorm:"comment('值') TEXT"` - Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` - Uid string `json:"uid" xorm:"not null default '' comment('') VARCHAR(255)"` + K string `json:"k" xorm:"not null pk VARCHAR(255)"` + V string `json:"v" xorm:"TEXT"` + Memo string `json:"memo" xorm:"VARCHAR(255)"` + Uid string `json:"uid" xorm:"comment('0是官方') VARCHAR(255)"` } diff --git a/app/db/model/master_withdrawal_flow.go b/app/db/model/master_withdrawal_flow.go new file mode 100644 index 0000000..d44a9b4 --- /dev/null +++ b/app/db/model/master_withdrawal_flow.go @@ -0,0 +1,25 @@ +package model + +import ( + "time" +) + +type MasterWithdrawalFlow struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + Uid string `json:"uid" xorm:"VARCHAR(255)"` + Time time.Time `json:"time" xorm:"DATETIME"` + UpdateTime time.Time `json:"update_time" xorm:"DATETIME"` + Remark string `json:"remark" xorm:"VARCHAR(255)"` + Alipay string `json:"alipay" xorm:"VARCHAR(255)"` + AlipayName string `json:"alipay_name" xorm:"VARCHAR(255)"` + Amount string `json:"amount" xorm:"default 0.00 DECIMAL(20,2)"` + Fee string `json:"fee" xorm:"default 0.00 DECIMAL(20,2)"` + Reason string `json:"reason" xorm:"VARCHAR(255)"` + Status string `json:"status" xorm:"VARCHAR(255)"` + CheckTime time.Time `json:"check_time" xorm:"DATETIME"` + Img string `json:"img" xorm:"VARCHAR(500)"` + RealAmount string `json:"real_amount" xorm:"default 0.00 DECIMAL(20,2)"` + HasInvoice int `json:"has_invoice" xorm:"default 0 comment('是否有发票') INT(1)"` + InvoiceBili string `json:"invoice_bili" xorm:"comment('发票比例') VARCHAR(255)"` + ExtendUid string `json:"extend_uid" xorm:"VARCHAR(255)"` +} diff --git a/app/db/model/playlet_sale_order.go b/app/db/model/playlet_sale_order.go index 8ecd581..8a950dc 100644 --- a/app/db/model/playlet_sale_order.go +++ b/app/db/model/playlet_sale_order.go @@ -6,19 +6,15 @@ import ( type PlayletSaleOrder struct { Id int `json:"id" xorm:"not null pk autoincr INT(11)"` - Uid string `json:"uid" xorm:"default '' comment('用户id') VARCHAR(255)"` - SubUid int `json:"sub_uid" xorm:"default 0 comment('') INT(11)"` + Uid string `json:"uid" xorm:"default '0' comment('用户id') VARCHAR(255)"` Data string `json:"data" xorm:"comment('第三方返回数据') VARCHAR(5000)"` - Oid string `json:"oid" xorm:"comment('订单号') VARCHAR(255)"` + Oid string `json:"oid" xorm:"comment('订单号') unique VARCHAR(255)"` Amount string `json:"amount" xorm:"default 0.00 comment('金额') DECIMAL(20,2)"` Commission string `json:"commission" xorm:"default 0.00 comment('佣金') DECIMAL(20,2)"` - PlatformFee string `json:"platform_fee" xorm:"default 0.00 comment('佣金') DECIMAL(20,2)"` - Fee string `json:"fee" xorm:"default 0.00 comment('佣金') DECIMAL(20,2)"` Status string `json:"status" xorm:"comment('状态') VARCHAR(255)"` CreateTime time.Time `json:"create_time" xorm:"comment('下单时间') DATETIME"` RefundTime time.Time `json:"refund_time" xorm:"comment('退款时间') DATETIME"` UpdateTime time.Time `json:"update_time" xorm:"comment('广告统计更新时间') DATETIME"` - PlatformSettleTime time.Time `json:"platform_settle_time" xorm:"comment('广告统计更新时间') DATETIME"` Title string `json:"title" xorm:"comment('标题') VARCHAR(255)"` VideoType string `json:"video_type" xorm:"comment('视频类型') VARCHAR(255)"` PlatformType string `json:"platform_type" xorm:"comment('平台类型') VARCHAR(255)"` @@ -27,6 +23,10 @@ type PlayletSaleOrder struct { OrdType string `json:"ord_type" xorm:"VARCHAR(255)"` TimesNum string `json:"times_num" xorm:"VARCHAR(255)"` PeopleNum string `json:"people_num" xorm:"VARCHAR(255)"` + SubUid int `json:"sub_uid" xorm:"default 0 INT(11)"` + PlatformSettleTime time.Time `json:"platform_settle_time" xorm:"DATETIME"` CustomOid string `json:"custom_oid" xorm:"VARCHAR(255)"` ExtendUid string `json:"extend_uid" xorm:"VARCHAR(255)"` + Fee string `json:"fee" xorm:"default 0.00 DECIMAL(20,2)"` + PlatformFee string `json:"platform_fee" xorm:"default 0.00 DECIMAL(20,2)"` } diff --git a/app/db/model/sys_cfg.go b/app/db/model/sys_cfg.go index 5508c9a..5159ef3 100644 --- a/app/db/model/sys_cfg.go +++ b/app/db/model/sys_cfg.go @@ -1,7 +1,7 @@ package model type SysCfg struct { - K string `json:"k" xorm:"not null pk comment('键') VARCHAR(127)"` - V string `json:"v" xorm:"comment('值') TEXT"` - Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` + K string `json:"k" xorm:"VARCHAR(255)"` + V string `json:"v" xorm:"TEXT"` + Memo string `json:"memo" xorm:"VARCHAR(255)"` } diff --git a/app/e/code.go b/app/e/code.go index cc8be46..3c29156 100644 --- a/app/e/code.go +++ b/app/e/code.go @@ -19,6 +19,7 @@ const ( ERR_ADMIN_API = 400012 ERR_QINIUAPI_RESPONSE = 400013 ERR_URL_TURNCHAIN = 400014 + ERR_TOKEN_EXPIRE = 401010 // 401 未授权 ERR_UNAUTHORIZED = 401000 @@ -124,6 +125,7 @@ var MsgFlags = map[int]string{ // 200 ERR_FILE_SAVE: "文件保存失败", // 400 + ERR_TOKEN_EXPIRE: "Token过期", ERR_BAD_REQUEST: "请求失败", ERR_INVALID_ARGS: "请求参数错误", ERR_API_RESPONSE: "API错误", diff --git a/app/hdl/hdl_file_upload.go b/app/hdl/hdl_file_upload.go new file mode 100644 index 0000000..6ca7f07 --- /dev/null +++ b/app/hdl/hdl_file_upload.go @@ -0,0 +1,52 @@ +package hdl + +import ( + "applet/app/db" + "applet/app/e" + "applet/app/lib/validate" + "applet/app/svc" + "applet/app/utils" + "github.com/gin-gonic/gin" + "github.com/mcuadros/go-defaults" +) + +func ImgReqUpload(c *gin.Context) { + var args struct { + DirName string `json:"dir_name,omitempty" default:"0"` + FileName string `json:"file_name" binding:"required" label:"文件名"` + FileSize int64 `json:"file_size" binding:"gt=1" label:"文件大小"` // 文件大小, 单位byte + } + defaults.SetDefaults(&args) + err := c.ShouldBindJSON(&args) + if err != nil { + err = validate.HandleValidateErr(err) + err1 := err.(e.E) + e.OutErr(c, err1.Code, err1.Error()) + return + } + + scheme := "http" + if c.Request.TLS != nil { + scheme = "https" + } + // 拼装回调地址 + callbackUrl := scheme + "://" + c.Request.Host + "/api/admin/file/upload/callback" + res, err := svc.ImgReqUpload(c, "", args.DirName, args.FileName, callbackUrl, args.FileSize) + if err != nil { + e.OutErr(c, e.ERR_BAD_REQUEST, err.Error()) + return + } + my := utils.SerializeStr(res) + var my1 map[string]interface{} + utils.Unserialize([]byte(my), &my1) + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + fileBucketRegion := masterListCfgDb.MasterListCfgGetOneData("0", "file_bucket_region") + if err != nil { + e.OutErr(c, e.ERR_BAD_REQUEST, err) + return + } + my1["host"] = fileBucketRegion + e.OutSuc(c, my1, nil) + +} diff --git a/app/hdl/hdl_file_upload_callback.go b/app/hdl/hdl_file_upload_callback.go new file mode 100644 index 0000000..093c14e --- /dev/null +++ b/app/hdl/hdl_file_upload_callback.go @@ -0,0 +1,45 @@ +package hdl + +import ( + "applet/app/db" + "applet/app/e" + "applet/app/md" + "applet/app/utils" + "fmt" + "github.com/gin-gonic/gin" +) + +func FileImgCallback(c *gin.Context) { + var args md.FileCallback + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, 200, e.ERR_INVALID_ARGS) + return + } + fmt.Println("callback args:", utils.SerializeStr(args)) + + res := map[string]interface{}{ + "name": args.FileName, + "fname": getFileNameURL(c, args.FileName), + "fsize": args.FileSize, + "provider": args.Provider, + "uid": args.Uid, + "dir_id": args.DirId, + "w": args.Width, + "h": args.Height, + } + fmt.Println("callback res:", utils.SerializeStr(res)) + + e.OutSuc(c, &res, nil) + +} + +func getFileNameURL(c *gin.Context, filename string) string { + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + protocol := masterListCfgDb.MasterListCfgGetOneData("0", "file_bucket_scheme") + domain := masterListCfgDb.MasterListCfgGetOneData("0", "file_bucket_host") + if protocol != "" && domain != "" { + return protocol + "://" + domain + "/" + filename + } + return filename +} diff --git a/app/hdl/hdl_token.go b/app/hdl/hdl_token.go new file mode 100644 index 0000000..145ac98 --- /dev/null +++ b/app/hdl/hdl_token.go @@ -0,0 +1,86 @@ +package hdl + +import ( + "applet/app/e" + "applet/app/md" + "applet/app/utils" + "applet/app/utils/cache" + "errors" + "time" + + "github.com/gin-gonic/gin" +) + +func GetAuthorizationCode(c *gin.Context) { + masterId := c.Query("master_id") + cacheKey := md.ZhimengAuthorizationCodeCacheKey + authorizationCode := utils.RandString(32) + _, err := cache.HSet(cacheKey, authorizationCode, masterId) + if err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + //设置过期日期 + _, err = cache.Expire(cacheKey, md.ZhimengAuthorizationCodeCacheTime*30) + if err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + e.OutSuc(c, map[string]interface{}{ + "authorization_code": authorizationCode, + }, nil) +} + +func GetToken(c *gin.Context) { + authorizationCode := c.Query("authorization_code") + cacheKey := md.ZhimengAuthorizationCodeCacheKey + get, err := cache.HGetString(cacheKey, authorizationCode) + if err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + if get == "" { + e.OutErr(c, e.ERR, errors.New("授权码有误")) + return + } + token, refreshToken, err := utils.GenToken(get) + if err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + e.OutSuc(c, map[string]interface{}{ + "token": token, + "refresh_token": refreshToken, + "master_id": get, + }, nil) +} + +func RefreshToken(c *gin.Context) { + var args struct { + RefreshToken string `json:"refresh_token"` + } + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + //1、验证refresh_token正确性 + //验证token字符串 + claim, err := utils.ParseRToken(args.RefreshToken) + if err != nil { + e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("refresh_token 验证失败")) + return + } + //过期判断 + if time.Now().Unix() > claim.ExpiresAt { + e.OutErr(c, e.ERR_TOKEN_EXPIRE, errors.New("refresh_token 过期已失效")) + return + } + + //2、生成新的token && refresh_token + token, refreshToken, err := utils.GenToken(claim.MasterId) + e.OutSuc(c, map[string]interface{}{ + "token": token, + "refresh_token": refreshToken, + "master_id": claim.MasterId, + }, nil) +} diff --git a/app/hdl/hdl_playlet_order.go b/app/hdl/zhimeng_internal/hdl_playlet_order.go similarity index 100% rename from app/hdl/hdl_playlet_order.go rename to app/hdl/zhimeng_internal/hdl_playlet_order.go diff --git a/app/hdl/zhimeng_platform/hdl_order_list.go b/app/hdl/zhimeng_platform/hdl_order_list.go new file mode 100644 index 0000000..e3a4413 --- /dev/null +++ b/app/hdl/zhimeng_platform/hdl_order_list.go @@ -0,0 +1,13 @@ +package zhimeng_platform + +import ( + "applet/app/svc/platform" + "github.com/gin-gonic/gin" +) + +func OrderList(c *gin.Context) { + platform.OrderList(c) +} +func OrderOutput(c *gin.Context) { + platform.OrderOutput(c) +} diff --git a/app/hdl/zhimeng_platform/hdl_withdrawal.go b/app/hdl/zhimeng_platform/hdl_withdrawal.go new file mode 100644 index 0000000..fdca9b1 --- /dev/null +++ b/app/hdl/zhimeng_platform/hdl_withdrawal.go @@ -0,0 +1,25 @@ +package zhimeng_platform + +import ( + "applet/app/svc/platform" + "github.com/gin-gonic/gin" +) + +func WithdrawalIncome(c *gin.Context) { + platform.WithdrawalIncome(c) +} +func WithdrawalList(c *gin.Context) { + platform.WithdrawalList(c) +} +func WithdrawalDoing(c *gin.Context) { + platform.WithdrawalDoing(c) +} +func WithdrawalOutput(c *gin.Context) { + platform.WithdrawalOutput(c) +} +func WithdrawalInvoiceImg(c *gin.Context) { + platform.WithdrawalInvoiceImg(c) +} +func WithdrawalBindAlipay(c *gin.Context) { + platform.WithdrawalBindAlipay(c) +} diff --git a/app/lib/auth/base.go b/app/lib/auth/base.go index d771802..b622fc1 100644 --- a/app/lib/auth/base.go +++ b/app/lib/auth/base.go @@ -8,8 +8,10 @@ import ( // TokenExpireDuration is jwt 过期时间 const TokenExpireDuration = time.Hour * 4380 +const RefreshTokenExpireDuration = time.Hour * 6 -var Secret = []byte("zyos") +var Secret = []byte("zyos_zhimeng") +var RSecret = []byte("zyos_zhimeng_refresh_token") // JWTUser 如果想要保存更多信息,都可以添加到这个结构体中 type JWTUser struct { @@ -17,3 +19,9 @@ type JWTUser struct { Username string `json:"username"` jwt.StandardClaims } + +// JWTMaster 如果想要保存更多信息,都可以添加到这个结构体中 +type JWTMaster struct { + MasterId string `json:"master_id"` + jwt.StandardClaims +} diff --git a/app/lib/qiniu/bucket_create.go b/app/lib/qiniu/bucket_create.go new file mode 100644 index 0000000..28d8106 --- /dev/null +++ b/app/lib/qiniu/bucket_create.go @@ -0,0 +1,16 @@ +package qiniu + +import ( + "github.com/qiniu/api.v7/v7/auth" + "github.com/qiniu/api.v7/v7/storage" +) + +func BucketCreate() error { + mac := auth.New(AK, SK) + cfg := storage.Config{ + // 是否使用https域名进行资源管理 + UseHTTPS: false, + } + bucketManager := storage.NewBucketManager(mac, &cfg) + return bucketManager.CreateBucket("", storage.RIDHuanan) +} diff --git a/app/lib/qiniu/bucket_delete.go b/app/lib/qiniu/bucket_delete.go new file mode 100644 index 0000000..6d41521 --- /dev/null +++ b/app/lib/qiniu/bucket_delete.go @@ -0,0 +1,18 @@ +package qiniu + +import ( + "github.com/qiniu/api.v7/v7/auth" + "github.com/qiniu/api.v7/v7/storage" +) + +func BucketDelete(bucketName string) error { + mac := auth.New(AK, SK) + + cfg := storage.Config{ + // 是否使用https域名进行资源管理 + UseHTTPS: false, + } + + bucketManager := storage.NewBucketManager(mac, &cfg) + return bucketManager.DropBucket(bucketName) +} diff --git a/app/lib/qiniu/bucket_get_domain.go b/app/lib/qiniu/bucket_get_domain.go new file mode 100644 index 0000000..f4cee3a --- /dev/null +++ b/app/lib/qiniu/bucket_get_domain.go @@ -0,0 +1,18 @@ +package qiniu + +import ( + "github.com/qiniu/api.v7/v7/auth" + "github.com/qiniu/api.v7/v7/storage" +) + +func BucketGetDomain(bucketName string) (string, error) { + mac := auth.New(AK, SK) + + cfg := storage.Config{UseHTTPS: false} + bucketManager := storage.NewBucketManager(mac, &cfg) + b, err := bucketManager.ListBucketDomains(bucketName) + if err != nil { + return "", err + } + return b[0].Domain, nil +} diff --git a/app/lib/qiniu/init.go b/app/lib/qiniu/init.go new file mode 100644 index 0000000..e44777a --- /dev/null +++ b/app/lib/qiniu/init.go @@ -0,0 +1,20 @@ +package qiniu + +import "applet/app/utils" + +var ( + AK = "MmxNdai23egjNUHjdzEVaTPdPCIbWzENz9BQuak3" + SK = "mElaFlM9O16rXp-ihoQdJ9KOH56naKm3MoyQBA59" + BUCKET = "dev-fnuoos" // 桶子名称 + BUCKET_SCHEME = "http" + BUCKET_REGION = "up-z2.qiniup.com" + Expires uint64 = 3600 +) + +func Init(ak, sk, bucket, region, scheme string) { + AK, SK, BUCKET, BUCKET_REGION, BUCKET_SCHEME = ak, sk, bucket, region, scheme +} + +func Sign(t string) string { + return utils.Md5(AK + SK + t) +} diff --git a/app/lib/qiniu/req_img_upload.go b/app/lib/qiniu/req_img_upload.go new file mode 100644 index 0000000..aad4d9d --- /dev/null +++ b/app/lib/qiniu/req_img_upload.go @@ -0,0 +1,54 @@ +package qiniu + +import ( + "applet/app/md" + "applet/app/utils" + "time" + + "github.com/qiniu/api.v7/v7/auth/qbox" + _ "github.com/qiniu/api.v7/v7/conf" + "github.com/qiniu/api.v7/v7/storage" +) + +// 请求图片上传地址信息 +func ReqImgUpload(f *md.FileCallback, callbackUrl string) interface{} { + if ext := utils.FileExt(f.FileName); ext == "png" || ext == "jpg" || ext == "jpeg" || ext == "gif" || ext == "bmp" || ext == "webp" { + f.Width = "$(imageInfo.width)" + f.Height = "$(imageInfo.height)" + } + f.Provider = "qiniu" + f.FileSize = "$(fsize)" + f.Hash = "$(etag)" + f.Bucket = "$(bucket)" + f.Mime = "$(mimeType)" + f.Time = utils.Int64ToStr(time.Now().Unix()) + f.Sign = Sign(f.Time) + putPolicy := storage.PutPolicy{ + Scope: BUCKET + ":" + f.FileName, // 使用覆盖方式时候必须请求里面有key,否则报错 + Expires: Expires, + ForceSaveKey: true, + SaveKey: f.FileName, + MimeLimit: "image/*", // 只允许上传图片 + CallbackURL: callbackUrl, + CallbackBody: utils.SerializeStr(f), + CallbackBodyType: "application/json", + } + return &struct { + Method string `json:"method"` + Key string `json:"key"` + Host string `json:"host"` + Token string `json:"token"` + }{Key: f.FileName, Method: "POST", Host: BUCKET_SCHEME + "://" + BUCKET_REGION, Token: putPolicy.UploadToken(qbox.NewMac(AK, SK))} +} + +/* +form表单上传 +地址 : http://upload-z2.qiniup.com +header + - Content-Type : multipart/form-data + +body : + - key : 文件名 + - token : 生成token + - file : 待上传文件 +*/ diff --git a/app/md/cfg_key.go b/app/md/cfg_key.go new file mode 100644 index 0000000..4ad7907 --- /dev/null +++ b/app/md/cfg_key.go @@ -0,0 +1,15 @@ +package md + +const ( + // 文件缓存的key + KEY_CFG_FILE_PVD = "file_provider" // 文件供应商 + KEY_CFG_FILE_BUCKET = "file_bucket" + KEY_CFG_FILE_REGION = "file_bucket_region" + KEY_CFG_FILE_HOST = "file_bucket_host" + KEY_CFG_FILE_SCHEME = "file_bucket_scheme" + KEY_CFG_FILE_AK = "file_access_key" + KEY_CFG_FILE_SK = "file_secret_key" + KEY_CFG_FILE_MAX_SIZE = "file_user_upload_max_size" + KEY_CFG_FILE_EXT = "file_ext" + KEY_CFG_FILE_AVATAR_THUMBNAIL = "file_avatar_thumbnail" // 默认头像缩略图参数,宽高120px,格式webp. +) diff --git a/app/md/file.go b/app/md/file.go new file mode 100644 index 0000000..db52eea --- /dev/null +++ b/app/md/file.go @@ -0,0 +1,54 @@ +package md + +// 用户拥有上传权限的目录, 目录ID + +const ( + FILE_DIR_FEEDBACK = "feedback" + FILE_DIR_AVATAR = "avatar" + FILE_DIR_QRCODE = "qrcode" + FILE_DIR_STYLE = "style" +) + +var ( + FileUserDir = map[string]string{ + FILE_DIR_FEEDBACK: "4", // 用户反馈 + FILE_DIR_AVATAR: "5", // 用户头像 + FILE_DIR_QRCODE: "6", // 用户微信二维码 + FILE_DIR_STYLE: "7", // 用户样式 + } +) + +// 文件回调信息 +type FileCallback struct { + Uid string `json:"uid"` + DirId string `json:"dir_id"` + Provider string `json:"provider"` // 供应商 + FileName string `json:"fname"` // 原文件名 + FileSize string `json:"fsize"` + Hash string `json:"hash"` + Bucket string `json:"bucket"` + Mime string `json:"mime"` + Width string `json:"w,omitempty"` + Height string `json:"h,omitempty"` + Time string `json:"time"` // 默认一个小时内要上传完毕,否则超时 + Sign string `json:"sign"` // 签名 +} + +type FileList struct { + Path string `json:"path"` + DirId int `json:"dir_id"` + FileName string `json:"f_name"` // 显示名称 + StgName string `json:"stg_name"` // 存储名字 + Ext string `json:"ext"` // 后缀名, png,jpg等 + FileSize string `json:"f_size"` + Provider string `json:"provider"` // 存储供应商 + Hash string `json:"hash"` + Bucket string `json:"bucket"` + Width int `json:"w"` + Height int `json:"h"` + Mime string `json:"mime"` + IsAdm bool `json:"is_adm"` //是否管理后台上传 + IsDir bool `json:"is_dir"` //是否文件夹 + CreateAt int `json:"create_at"` + Url string `json:"url"` +} diff --git a/app/md/md_app_redis_key.go b/app/md/md_app_redis_key.go index 4f93079..592dca4 100644 --- a/app/md/md_app_redis_key.go +++ b/app/md/md_app_redis_key.go @@ -7,4 +7,11 @@ const ( CfgCacheTime = 86400 AppCfgCacheKey = "one_item_one_code:%s" // 占位符: key的第一个字母 WxOfficialAccountCacheKey = "wx_official_account" // 占位符: key的第一个字母 + + ZhimengIsUseCacheKey = "zhimeng_is_use_cache" //授权码 + ZhimengAuthorizationCodeCacheKey = "zhimeng_authorization_code_cache" //授权码 + ZhimengAuthorizationCodeCacheTime = 60 + + ZhimengDataRequestCacheKey = "%s:zhimeng_data_request_cache:%s:%s" //请求缓存(masterId:big_data_screen_data_request_cache:uri:md5(body参数)) + ) diff --git a/app/md/md_playlet.go b/app/md/md_playlet.go new file mode 100644 index 0000000..c5af739 --- /dev/null +++ b/app/md/md_playlet.go @@ -0,0 +1,4 @@ +package md + +var OrdTypeMap = map[string]string{"video": "短剧", "adv": "广告"} +var VideoTypeMap = map[string]string{"channel": "视频号", "douyin": "抖音", "kuaishou": "快手"} diff --git a/app/mw/mw_auth_jwt.go b/app/mw/mw_auth_jwt.go new file mode 100644 index 0000000..a6b2f3c --- /dev/null +++ b/app/mw/mw_auth_jwt.go @@ -0,0 +1,51 @@ +package mw + +import ( + "applet/app/e" + "applet/app/utils" + "errors" + "github.com/dgrijalva/jwt-go" + "strings" + "time" + + "github.com/gin-gonic/gin" +) + +// AuthJWT is jwt middleware +func AuthJWT(c *gin.Context) { + + //获取请求头中的Authorization + authHeader := c.Request.Header.Get("Authorization") + if authHeader == "" { + e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("token 不能为空")) + return + } + + //拆分Authorization字段获取token字符串 + parts := strings.SplitN(authHeader, " ", 2) + if !(len(parts) == 2 && parts[0] == "Bearer") { + e.OutErr(c, e.ERR_TOKEN_FORMAT, errors.New("token 格式不对")) + return + } + + //验证token字符串 + claim, err := utils.ParseToken(parts[1]) + if err != nil { + v, _ := err.(*jwt.ValidationError) + if v.Errors == jwt.ValidationErrorExpired { + e.OutErr(c, e.ERR_TOKEN_EXPIRE, errors.New("token 过期已失效")) + return + } + e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("token 验证失败")) + return + } + + //过期判断 + if time.Now().Unix() > claim.ExpiresAt { + e.OutErr(c, e.ERR_TOKEN_EXPIRE, errors.New("token 过期已失效")) + return + } + //设置上下文信息 + c.Set("master_id", claim.MasterId) + c.Next() +} diff --git a/app/mw/mw_init_validator.go b/app/mw/mw_init_validator.go new file mode 100644 index 0000000..8283c20 --- /dev/null +++ b/app/mw/mw_init_validator.go @@ -0,0 +1,18 @@ +package mw + +import ( + "applet/app/e" + "applet/app/utils" + "fmt" + "github.com/gin-gonic/gin" +) + +func InitReqValidator(c *gin.Context) { + // 初始化翻译器 + if err := utils.ValidatorTransInitZh(); err != nil { + e.OutErr(c, e.ERR, fmt.Sprintf("init trans failed, err:%v\n", err)) + return + } + + c.Next() +} diff --git a/app/mw/mw_request_cache.go b/app/mw/mw_request_cache.go new file mode 100644 index 0000000..bb7261c --- /dev/null +++ b/app/mw/mw_request_cache.go @@ -0,0 +1,61 @@ +package mw + +import ( + "applet/app/e" + "applet/app/md" + "applet/app/utils" + "applet/app/utils/cache" + "bytes" + "fmt" + "github.com/gin-gonic/gin" + "io/ioutil" +) + +//自己实现一个type gin.ResponseWriter interface +type responseWriter struct { + gin.ResponseWriter + b *bytes.Buffer +} + +//重写Write([]byte) (int, error) +func (w responseWriter) Write(b []byte) (int, error) { + //向一个bytes.buffer中再写一份数据 + w.b.Write(b) + //完成gin.Context.Writer.Write()原有功能 + return w.ResponseWriter.Write(b) +} + +// RequestCache is cache middleware +func RequestCache(c *gin.Context) { + tempMasterId, _ := c.Get("master_id") + masterId := tempMasterId.(string) + uri := c.Request.RequestURI + md5Params := dealBodyParams(c) + cacheKey := fmt.Sprintf(md.ZhimengDataRequestCacheKey, masterId, uri, md5Params) + //自己实现一个type gin.ResponseWriter + writer := responseWriter{ + c.Writer, + bytes.NewBuffer([]byte{}), + } + isUse, _ := cache.GetInt(md.ZhimengIsUseCacheKey) + var res = map[string]interface{}{} + cache.GetJson(cacheKey, &res) + if res["data"] != nil && isUse == 1 { + e.OutSuc(c, res["data"], nil) + return + } + c.Writer = writer + c.Next() +} + +func dealBodyParams(c *gin.Context) (md5Params string) { + body, err := c.GetRawData() + if err != nil { + panic(err) + } + fmt.Println(">>>>>>>>>>string<<<<<<<<<<<", string(body)) + md5Params = utils.Md5(string(body)) + //TODO::把读过的字节流重新放到body + c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + return +} diff --git a/app/router/router.go b/app/router/router.go index 66e1a51..bbf2c90 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -3,6 +3,9 @@ package router import ( "applet/app/cfg" "applet/app/hdl" + internalHdl "applet/app/hdl/zhimeng_internal" + platformHdl "applet/app/hdl/zhimeng_platform" + "applet/app/mw" "github.com/gin-gonic/gin" ) @@ -37,14 +40,15 @@ func Init() *gin.Engine { c.JSON(405, gin.H{"code": 405, "msg": "method not allowed", "data": []struct{}{}}) }) r.Use(mw.Cors) - routeInternal(r.Group("/api/v1/internal")) + routeInternal(r.Group("/api/internal")) + routeZhimeng(r.Group("/api/admin")) return r } func routeInternal(r *gin.RouterGroup) { r.Use(mw.DB) // 以下接口需要用到数据库 { - r.POST("/playlet_order", hdl.GetPlayletOrder) + r.POST("/playlet_order", internalHdl.GetPlayletOrder) } r.Use(mw.Checker) // 以下接口需要检查Header: platform @@ -56,3 +60,23 @@ func routeInternal(r *gin.RouterGroup) { } } +func routeZhimeng(r *gin.RouterGroup) { + r.GET("/authorizationCode", hdl.GetAuthorizationCode) + r.GET("/token", hdl.GetToken) + r.POST("/rToken", hdl.RefreshToken) + r.POST("/file/upload/token", mw.InitReqValidator, hdl.ImgReqUpload) // 文件上传获取七牛云上传token + r.POST("/file/upload/callback", hdl.FileImgCallback) // 文件上传回调 + + r.Use(mw.AuthJWT, mw.RequestCache) // 以下接口需要JWT验证 + { + r.POST("/order_list", platformHdl.OrderList) + r.POST("/order_output", platformHdl.OrderOutput) + r.POST("/withdrawal_income", platformHdl.WithdrawalIncome) + r.POST("/withdrawal_bind_alipay", platformHdl.WithdrawalBindAlipay) + r.POST("/withdrawal_list", platformHdl.WithdrawalList) + r.POST("/withdrawal_doing", platformHdl.WithdrawalDoing) + r.POST("/withdrawal_output", platformHdl.WithdrawalOutput) + r.POST("/withdrawal_invoice_img", platformHdl.WithdrawalInvoiceImg) + + } +} diff --git a/app/svc/platform/svc_order_list.go b/app/svc/platform/svc_order_list.go new file mode 100644 index 0000000..0cb21a9 --- /dev/null +++ b/app/svc/platform/svc_order_list.go @@ -0,0 +1,139 @@ +package platform + +import ( + "applet/app/db" + "applet/app/e" + "applet/app/md" + "applet/app/utils" + "github.com/gin-gonic/gin" + "time" +) + +func OrderList(c *gin.Context) { + var args map[string]string + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + masterId, _ := c.Get("master_id") + playletSaleOrderDb := db.PlayletSaleOrderDb{} + playletSaleOrderDb.Set() + args["mid"] = utils.AnyToString(masterId) + args["sort"] = "create_time desc,id desc" + list, total := playletSaleOrderDb.GetPlayletVideoOrderListAndTotal(args) + var data = make([]map[string]string, 0) + + if list != nil { + for _, v := range *list { + source := md.OrdTypeMap[v.OrdType] + md.VideoTypeMap[v.VideoType] + settleStatus := "未结算" + settleTime := "-" + if v.SettleTime > 0 { + settleStatus = "已结算" + settleTime = time.Unix(int64(v.SettleTime), 0).Format("2006-01-02 15:04:05") + } + var tmp = map[string]string{ + "oid": v.Oid, + "mid": v.Uid, + "custom_oid": v.CustomOid, + "title": v.Title, + "source": source, + "amount": v.Amount, + "platform_fee": v.PlatformFee, + "commission": v.Commission, + "status": v.Status, + "settle_status": settleStatus, + "create_time": v.CreateTime.Format("2006-01-02 15:04:05"), + "settle_time": settleTime, + "commission_bili": "-", + } + if utils.StrToFloat64(v.Commission) > 0 { + tmp["commission_bili"] = utils.Float64ToStr(utils.StrToFloat64(v.Commission)/utils.StrToFloat64(v.Amount)*100) + "%" + } + data = append(data, tmp) + } + } + sourceList := []map[string]string{ + {"name": "短剧", "value": "video"}, + {"name": "广告", "value": "adv"}, + } + videoList := []map[string]string{ + {"name": "抖音", "value": "douyin"}, + {"name": "快手", "value": "kuaishou"}, + {"name": "视频号", "value": "channel"}, + } + statusList := []map[string]string{ + {"name": "订单付款", "value": "订单付款"}, + {"name": "订单结算", "value": "订单结算"}, + } + settleStatusList := []map[string]string{ + {"name": "未结算", "value": "未结算"}, + {"name": "已结算", "value": "已结算"}, + } + var res = map[string]interface{}{ + "list": data, + "total": total, + "source_list": sourceList, + "video_ist": videoList, + "status_list": statusList, + "settle_status_list": settleStatusList, + } + e.OutSuc(c, res, nil) + return +} + +func OrderOutput(c *gin.Context) { + var args map[string]string + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + masterId, _ := c.Get("master_id") + playletSaleOrderDb := db.PlayletSaleOrderDb{} + playletSaleOrderDb.Set() + args["mid"] = utils.AnyToString(masterId) + args["size"] = "3000" + if args["ids"] != "" { + args["size"] = "0" + } + name := "订单_" + args["p"] + //写入数据 + data := map[string]string{ + "A1": "订单号", + "B1": "会员ID", + "C1": "标题", + "D1": "来源", + "E1": "结算时间", + "F1": "订单状态", + "G1": "金额", + "H1": "佣金", + } + list := playletSaleOrderDb.GetPlayletVideoOrderListWithCreateTime(args) + if list != nil { + for k, v := range *list { + source := md.OrdTypeMap[v.OrdType] + md.VideoTypeMap[v.PlatformType] + settleTime := "-" + if v.SettleTime > 0 { + settleTime = time.Unix(int64(v.SettleTime), 0).Format("2006-01-02 15:04:05") + } + i := utils.IntToStr(k + 2) + data["A"+i] = v.Oid + data["B"+i] = utils.IntToStr(v.SubUid) + data["C"+i] = v.Title + data["D"+i] = source + data["E"+i] = settleTime + data["F"+i] = v.Status + data["G"+i] = v.Amount + data["H"+i] = v.Commission + } + } + + file := utils.Output(c, name, data) + filename := name + ".xlsx" + r := map[string]string{ + "file": file, + "filename": filename, + } + e.OutSuc(c, r, nil) + return +} diff --git a/app/svc/platform/svc_withdrawal.go b/app/svc/platform/svc_withdrawal.go new file mode 100644 index 0000000..20143a1 --- /dev/null +++ b/app/svc/platform/svc_withdrawal.go @@ -0,0 +1,386 @@ +package platform + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/utils" + "applet/app/utils/cache" + "encoding/json" + "fmt" + "github.com/gin-gonic/gin" + "time" +) + +func WithdrawalIncome(c *gin.Context) { + args, mid, err := commArg(c) + if err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + fmt.Println(args) + fmt.Println(mid) + if args["type"] == "" { + args["type"] = "playlet" + } + amountMap := masterAmount(mid, args["type"]) + monthAmountMap := masterMonthAmount(mid) + isNeedBingAlipay := "1" + if amountMap["alipay"] != "" { + isNeedBingAlipay = "0" + } + var res = []map[string]string{ + {"name": "账户余额", "value": amountMap["amount"], "type": "amount", "tip": "", "alipay": amountMap["alipay"], "alipay_name": amountMap["alipay_name"], "is_need_bing_alipay": isNeedBingAlipay, "is_show_withdrawal": "1"}, + {"name": "上月预估收益", "value": monthAmountMap["last_month_amount"], "type": "last_month_amount", "tip": "", "is_need_bing_alipay": "0", "is_show_withdrawal": "0"}, + {"name": "上月预估结算收益", "value": amountMap["last_month_settle_amount"], "type": "last_month_settle_amount", "tip": "", "is_need_bing_alipay": "0", "is_show_withdrawal": "0"}, + {"name": "本月预估收益", "value": monthAmountMap["month_amount"], "type": "month_amount", "tip": "", "is_need_bing_alipay": "0", "is_show_withdrawal": "0"}, + {"name": "本月预估结算收益", "value": monthAmountMap["month_settle_amount"], "type": "month_settle_amount", "tip": "", "is_need_bing_alipay": "0", "is_show_withdrawal": "0"}, + } + e.OutSuc(c, res, nil) + return +} +func WithdrawalList(c *gin.Context) { + args, mid, err := commArg(c) + if err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + amountMap := masterAmount(mid, args["type"]) + masterWithdrawalFlowDb := db.MasterWithdrawalFlowDb{} + masterWithdrawalFlowDb.Set() + list, total := masterWithdrawalFlowDb.GetWithdrawalFlowListWithTotal(amountMap["id"], args) + data := make([]map[string]string, 0) + if list != nil { + for _, v := range *list { + var tmp = map[string]string{ + "id": utils.IntToStr(v.Id), + "alipay": v.Alipay, + "alipay_name": v.AlipayName, + "amount": v.Amount, + "real_amount": v.RealAmount, + "fee": v.Fee, + "time": v.Time.Format("2006-01-02 15:04:05"), + "check_time": "", + "status": v.Status, + "remark": v.Remark, + "reason": v.Reason, + "img": v.Img, + "is_need_upload_invoice": utils.IntToStr(v.HasInvoice), + } + if v.Img != "" { + tmp["is_need_upload_invoice"] = "0" + } + if v.CheckTime.IsZero() == false { + tmp["check_time"] = v.CheckTime.Format("2006-01-02 15:04:05") + } + data = append(data, tmp) + } + } + statusList := []map[string]string{ + {"name": "提现审核", "value": "提现审核"}, + {"name": "提现成功", "value": "提现成功"}, + {"name": "提现失败", "value": "提现失败"}, + } + var res = map[string]interface{}{ + "list": data, "total": total, "status_list": statusList, + } + e.OutSuc(c, res, nil) + return +} +func WithdrawalDoing(c *gin.Context) { + args, mid, err := commArg(c) + if err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + if utils.StrToFloat64(args["amount"]) <= 0 { + e.OutErr(c, 400, e.NewErr(400, "金额不正确")) + return + } + masterdb := db.MasterDb{} + masterdb.Set() + master := masterdb.GetMaster(mid) + if master == nil { + e.OutErr(c, 400, e.NewErr(400, "用户不存在")) + return + } + amountMap := masterAmount(mid, args["type"]) + leaveAmount := utils.StrToFloat64(amountMap["amount"]) - utils.StrToFloat64(args["amount"]) + if leaveAmount < 0 { + e.OutErr(c, 400, e.NewErr(400, "余额不足")) + return + } + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + withdrawalBili := masterListCfgDb.MasterListCfgGetOneData("0", "withdrawal_bili") + invoiceBili := masterListCfgDb.MasterListCfgGetOneData("0", "invoice_bili") + withdrawalDay := masterListCfgDb.MasterListCfgGetOneData("0", "withdrawal_day") + if time.Now().Day() != utils.StrToInt(withdrawalDay) && utils.StrToInt(withdrawalDay) > 0 { + e.OutErr(c, 400, e.NewErr(400, "每月"+withdrawalDay+"号提现")) + return + } + var fee float64 = 0 + if utils.StrToFloat64(withdrawalBili) > 0 { + bili := utils.StrToFloat64(withdrawalBili) / 100 + var invoiceBiliMap = make([]string, 0) + json.Unmarshal([]byte(invoiceBili), &invoiceBiliMap) + if utils.InArr(args["invoice_bili"], invoiceBiliMap) == false && utils.StrToInt(args["has_invoice"]) == 1 { + e.OutErr(c, 400, e.NewErr(400, "发票税率不正确")) + return + } + //开了发票的话再扣掉对应的发票比例 + if utils.InArr(args["invoice_bili"], invoiceBiliMap) && utils.StrToInt(args["has_invoice"]) == 1 { + bili -= utils.StrToFloat64(args["invoice_bili"]) / 100 + } + fee = utils.StrToFloat64(args["amount"]) * bili + } + realAmount := utils.StrToFloat64(args["amount"]) - fee + if amountMap["alipay"] == "" { + e.OutErr(c, 400, e.NewErr(400, "未绑定支付宝")) + return + } + + mutexKey := fmt.Sprintf("withdrawal:%s", amountMap["id"]) + withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 30, "NX") + if err != nil { + e.OutErr(c, e.ERR, err) + return + } + if withdrawAvailable != "OK" { + e.OutErr(c, e.ERR, e.NewErr(400000, "操作过于频繁,请稍后再试")) + return + } + sess := db.ZhimengDb.NewSession() + err = sess.Begin() + if err != nil { + sess.Rollback() + e.OutErr(c, 400, e.NewErr(400000, "请重试")) + return + } + defer sess.Close() + //先扣钱 + amountData := db.GetMasterAmountByListIdWithSess(sess, amountMap["list_id"]) + if amountData == nil { + sess.Rollback() + e.OutErr(c, e.ERR, e.NewErr(400000, "提现失败")) + return + } + oldAmount := amountData.Amount + leaveAmount = utils.StrToFloat64(amountData.Amount) - utils.StrToFloat64(args["amount"]) + if leaveAmount < 0 { + e.OutErr(c, 400, e.NewErr(400, "余额不足")) + return + } + amountData.Amount = utils.Float64ToStr(leaveAmount) + update := db.MasterAmountUpdateWithSess(sess, amountData.Id, amountData) + if update == false { + e.OutErr(c, e.ERR, e.NewErr(400000, "提现失败")) + return + } + //再写入明细 + var tmpFlow = model.MasterAmountFlow{ + Uid: amountMap["id"], + Time: time.Now(), + BeforeAmount: oldAmount, + Amount: args["amount"], + AfterAmount: amountData.Amount, + Platform: args["type"], + Oid: "", + Title: "提现", + FlowType: "withdrawal", + ExtendUid: master.ExtendUid, + } + flowInsert := db.MasterAmountFlowInsertWithSess(sess, &tmpFlow) + if flowInsert == false { + e.OutErr(c, e.ERR, e.NewErr(400000, "提现失败")) + return + } + var tmp = model.MasterWithdrawalFlow{ + Uid: amountMap["id"], + Time: time.Now(), + UpdateTime: time.Now(), + Remark: args["remark"], + Alipay: amountMap["alipay"], + AlipayName: amountMap["alipay_name"], + Amount: args["amount"], + RealAmount: utils.Float64ToStr(realAmount), + Fee: utils.Float64ToStr(fee), + Reason: "", + Status: "提现审核", + HasInvoice: utils.StrToInt(args["has_invoice"]), + InvoiceBili: args["invoice_bili"], + ExtendUid: master.ExtendUid, + } + insert := db.MasterWithdrawalFlowInsertWithSess(sess, &tmp) + if insert == false { + e.OutErr(c, e.ERR, e.NewErr(400000, "提现失败")) + return + } + sess.Commit() + e.OutSuc(c, "success", nil) + return +} +func WithdrawalOutput(c *gin.Context) { + args, mid, err := commArg(c) + if err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + args["size"] = "3000" + amountMap := masterAmount(mid, args["type"]) + masterWithdrawalFlowDb := db.MasterWithdrawalFlowDb{} + masterWithdrawalFlowDb.Set() + list := masterWithdrawalFlowDb.GetWithdrawalFlowList(amountMap["id"], args) + name := "订单_" + args["p"] + //写入数据 + data := map[string]string{ + "A1": "提现支付宝账号", + "B1": "提现支付宝姓名", + "C1": "提现金额", + "D1": "实际金额", + "E1": "手续费", + "F1": "提现状态", + "G1": "申请时间", + "H1": "审核时间", + "I1": "备注", + "J1": "失败原因", + } + if list != nil { + for k, v := range *list { + checkTime := "" + if v.CheckTime.IsZero() == false { + checkTime = v.CheckTime.Format("2006-01-02 15:04:05") + } + i := utils.IntToStr(k + 2) + data["A"+i] = v.Alipay + data["B"+i] = v.AlipayName + data["C"+i] = v.Amount + data["D"+i] = v.RealAmount + data["E"+i] = v.Fee + data["F"+i] = v.Status + data["G"+i] = v.Time.Format("2006-01-02 15:04:05") + data["H"+i] = checkTime + data["I"+i] = v.Remark + data["J"+i] = v.Reason + } + } + file := utils.Output(c, name, data) + filename := name + ".xlsx" + r := map[string]string{ + "file": file, + "filename": filename, + } + e.OutSuc(c, r, nil) + return +} +func WithdrawalInvoiceImg(c *gin.Context) { + var args map[string]string + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + masterWithdrawalFlowDb := db.MasterWithdrawalFlowDb{} + masterWithdrawalFlowDb.Set() + flow := masterWithdrawalFlowDb.MasterWithdrawalFlowById(args["id"]) + flow.Img = args["img"] + update := masterWithdrawalFlowDb.MasterWithdrawalFlowInsertUpdate(flow) + if update == false { + e.OutErr(c, 400, e.NewErr(400, "上传失败")) + return + } + e.OutSuc(c, "success", nil) + return +} + +func WithdrawalBindAlipay(c *gin.Context) { + var args map[string]string + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + if args["alipay"] == "" || args["alipay_name"] == "" { + e.OutErr(c, 400, e.NewErr(400, "支付宝信息不能为空")) + return + } + masterId, _ := c.Get("master_id") + mid := utils.AnyToString(masterId) + masterDb := db.MasterDb{} + masterDb.Set() + master := masterDb.GetMaster(mid) + master.AlipayName = args["alipay_name"] + master.Alipay = args["alipay"] + update := masterDb.MasterUpdate(master) + if update == false { + e.OutErr(c, 400, e.NewErr(400, "修改失败")) + return + } + e.OutSuc(c, "success", nil) + return +} + +func commArg(c *gin.Context) (map[string]string, string, error) { + masterId, _ := c.Get("master_id") + mid := utils.AnyToString(masterId) + fmt.Println(mid) + var args map[string]string + if err := c.ShouldBindJSON(&args); err != nil { + return args, mid, err + } + return args, mid, nil + +} + +func masterInfo(mid string) map[string]string { + masterDb := db.MasterDb{} + masterDb.Set() + master := masterDb.GetMaster(mid) + res := make(map[string]string) + if master != nil { + res["id"] = utils.IntToStr(master.Id) + res["alipay"] = master.Alipay + res["alipay_name"] = master.AlipayName + } + return res +} +func masterAmount(mid, types string) map[string]string { + masterInfos := masterInfo(mid) + res := map[string]string{ + "amount": "0.00", + "last_month_settle_amount": "0.00", + } + if masterInfos["id"] == "" { + return res + } + masterAmountDb := db.MasterAmountDb{} + masterAmountDb.Set() + masterAmounts := masterAmountDb.GetMasterAmount(masterInfos["id"], types) + if masterAmounts == nil { + return res + } + res["amount"] = masterAmounts.Amount + if res["amount"] == "" { + res["amount"] = "0" + } + res["id"] = masterAmounts.Uid + res["list_id"] = utils.IntToStr(masterAmounts.Id) + res["alipay"] = masterInfos["alipay"] + res["alipay_name"] = masterInfos["alipay_name"] + res["last_month_settle_amount"] = masterAmounts.LastMonthAmount + if res["last_month_settle_amount"] == "" { + res["last_month_settle_amount"] = "0" + } + return res +} +func masterMonthAmount(mid string) map[string]string { + playletSaleOrder := db.PlayletSaleOrderDb{} + playletSaleOrder.Set() + lastMonthSum := playletSaleOrder.PlayletVideoOrderSum(mid, "", "last_month") + monthSum := playletSaleOrder.PlayletVideoOrderSum(mid, "", "current_month") + monthSettleSum := playletSaleOrder.PlayletVideoOrderSum(mid, "订单结算", "current_month") + res := map[string]string{ + "last_month_amount": utils.Float64ToStr(lastMonthSum), + "month_amount": utils.Float64ToStr(monthSum), + "month_settle_amount": utils.Float64ToStr(monthSettleSum), + } + return res +} diff --git a/app/svc/svc_file_upload.go b/app/svc/svc_file_upload.go new file mode 100644 index 0000000..df57546 --- /dev/null +++ b/app/svc/svc_file_upload.go @@ -0,0 +1,68 @@ +package svc + +import ( + "applet/app/db" + "applet/app/e" + "applet/app/lib/qiniu" + "applet/app/md" + "applet/app/utils" + "errors" + "fmt" + "github.com/gin-gonic/gin" + "strings" + "time" +) + +// 请求文件上传 +func ImgReqUpload(c *gin.Context, uid, dirName, fname, callbackUrl string, fsize int64) (interface{}, error) { + ext := utils.FileExt(fname) + if err := initStg(c, fsize, ext); err != nil { + return nil, err + } + pureFileName := strings.Replace(fname, "."+ext, "", 1) + pureFileName += "-" + utils.RandString(6, utils.AnyToString(time.Now().UnixNano())) + newName := dirName + "/" + pureFileName + "." + ext + + f := &md.FileCallback{ + Uid: uid, + DirId: dirName, + FileName: newName, + } + return qiniu.ReqImgUpload(f, callbackUrl), nil +} + +func initStg(c *gin.Context, fsize int64, ext string) error { + // 获取上传配置 + fileCfg := make(map[string]string) + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + fileCfg[md.KEY_CFG_FILE_BUCKET] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_BUCKET) + fileCfg[md.KEY_CFG_FILE_HOST] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_HOST) + fileCfg[md.KEY_CFG_FILE_AK] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_AK) + fileCfg[md.KEY_CFG_FILE_SK] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_SK) + fileCfg[md.KEY_CFG_FILE_PVD] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_PVD) + fileCfg[md.KEY_CFG_FILE_MAX_SIZE] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_MAX_SIZE) + fileCfg[md.KEY_CFG_FILE_EXT] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_EXT) + fileCfg[md.KEY_CFG_FILE_SCHEME] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_SCHEME) + utils.FilePutContents("initStg", fmt.Sprintf("[KEY_CFG_FILE_BUCKET]:%s ; [KEY_CFG_FILE_HOST]:%s ; [KEY_CFG_FILE_AK]::%s;"+ + " [KEY_CFG_FILE_SK]::%s, ;[KEY_CFG_FILE_PVD]::%s, ;[KEY_CFG_FILE_REGION]::%s, ;[KEY_CFG_FILE_MAX_SIZE]::%s, ;[KEY_CFG_FILE_EXT]::%s, ;[KEY_CFG_FILE_SCHEME]::%s, "+ + ">>>>>>>>>>>>>>>>>>>>", fileCfg[md.KEY_CFG_FILE_BUCKET], fileCfg[md.KEY_CFG_FILE_HOST], fileCfg[md.KEY_CFG_FILE_AK], fileCfg[md.KEY_CFG_FILE_SK], + fileCfg[md.KEY_CFG_FILE_PVD], fileCfg[md.KEY_CFG_FILE_REGION], fileCfg[md.KEY_CFG_FILE_MAX_SIZE], fileCfg[md.KEY_CFG_FILE_EXT], fileCfg[md.KEY_CFG_FILE_SCHEME])) + for _, v := range fileCfg { + if v == "" { + return errors.New("上传配置不完整") + } + } + + qiniu.Init(fileCfg[md.KEY_CFG_FILE_AK], fileCfg[md.KEY_CFG_FILE_SK], fileCfg[md.KEY_CFG_FILE_BUCKET], fileCfg[md.KEY_CFG_FILE_REGION], fileCfg[md.KEY_CFG_FILE_SCHEME]) + + // 检查文件大小限制 + if utils.StrToInt64(fileCfg[md.KEY_CFG_FILE_MAX_SIZE]) < fsize { + return e.NewErrCode(e.ERR_FILE_MAX_SIZE) + } + // 检查文件后缀 + if !strings.Contains(fileCfg[md.KEY_CFG_FILE_EXT], ext) { + return e.NewErrCode(e.ERR_FILE_EXT) + } + return nil +} diff --git a/app/task/init.go b/app/task/init.go index 56a6a85..b13da38 100644 --- a/app/task/init.go +++ b/app/task/init.go @@ -69,6 +69,7 @@ func reload() { func doTask(fnName string) func() { return func() { begin := time.Now().Local() + jobs[fnName]() end := time.Now().Local() logx.Infof( " AutoTask <%s> started at <%s>, ended at <%s> duration <%s>", @@ -90,4 +91,8 @@ func initTasks() { jobs[taskMd.ZhimengCronPlayletAdvOrderYesterDay] = taskPlayletAdvOrderYesterday // jobs[taskMd.ZhimengCronPlayletAdvOrderYesterDayToMoney] = taskPlayletAdvOrderYesterdayToMoney // jobs[taskMd.ZhimengCronPlayletGoods] = taskPlayletGoods // + + jobs[taskMd.ZhimengCronPlayletOrderSettle] = taskPlayletOrderSettle // + jobs[taskMd.ZhimengCronMasterMonthSettle] = taskMasterMonthSettle // + } diff --git a/app/task/md/cron_key.go b/app/task/md/cron_key.go index 3405837..b71651d 100644 --- a/app/task/md/cron_key.go +++ b/app/task/md/cron_key.go @@ -9,4 +9,7 @@ const ( ZhimengCronPlayletAdvOrderMonth = "zhimeng_cron_playlet_adv_order_month" ZhimengCronPlayletAdvOrderYesterDayToMoney = "zhimeng_cron_playlet_adv_order_yesterday_to_money" ZhimengCronPlayletGoods = "zhimeng_cron_playlet_goods" + + ZhimengCronPlayletOrderSettle = "zhimeng_cron_playlet_order_settle" + ZhimengCronMasterMonthSettle = "zhimeng_cron_master_month_settle" ) diff --git a/app/task/md/playlet_order.go b/app/task/md/playlet_order.go index 0c6e179..7f3180f 100644 --- a/app/task/md/playlet_order.go +++ b/app/task/md/playlet_order.go @@ -1,20 +1,21 @@ package md type PlayletVideoOrder struct { - Appid int `json:"appid"` - Channel string `json:"channel"` + Appid string `json:"appid"` OrderId string `json:"order_id"` - PayDate string `json:"pay_date"` + SettleType string `json:"settle_type"` Price int `json:"price"` + Title string `json:"title"` + Status int `json:"status"` + PayDate string `json:"pay_date"` RefundDate string `json:"refund_date"` SourceId string `json:"source_id"` - Status int `json:"status"` - Title string `json:"title"` SourceType string `json:"source_type"` - SettleType string `json:"settle_type"` + MemberId string `json:"member_id"` + Channel string `json:"channel"` } type PlayletAdvOrder struct { - Appid int `json:"appid"` + Appid string `json:"appid"` Channel string `json:"channel"` CreatedTime string `json:"created_time"` Price int `json:"price"` diff --git a/app/task/svc/svc_master_month_settle.go b/app/task/svc/svc_master_month_settle.go new file mode 100644 index 0000000..3c9d0d2 --- /dev/null +++ b/app/task/svc/svc_master_month_settle.go @@ -0,0 +1,91 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/utils" + "applet/app/utils/cache" + "fmt" + "time" +) + +func MasterMonthSettle() { + day := time.Now().Day() + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + withdrawalDay := masterListCfgDb.MasterListCfgGetOneData("0", "withdrawal_day") + if day < utils.StrToInt(withdrawalDay) { + return + } + args := map[string]string{ + "p": "1", + "size": "100", + } + masterAmountDb := db.MasterAmountDb{} + masterAmountDb.Set() + list := masterAmountDb.GetMasterAmountList(args) + if list == nil { + return + } + for _, v := range *list { + mutexKey := fmt.Sprintf("master_month_settle:%d", v.Id) + withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 1800, "NX") + if err != nil { + continue + } + if withdrawAvailable != "OK" { + continue + } + if utils.StrToFloat64(v.LastMonthAmount) <= 0 { + continue + } + masterDb := db.MasterDb{} + masterDb.Set() + master := masterDb.GetMasterId(v.Id) + if master == nil { + continue + } + oldAmount := v.Amount + oldLastMonthAmount := v.LastMonthAmount + v.Amount = utils.Float64ToStr(utils.StrToFloat64(v.Amount) + utils.StrToFloat64(v.LastMonthAmount)) + v.LastMonthAmount = "0" + update := masterAmountDb.MasterAmountUpdate(v.Id, &v) + if update == false { + continue + } + var tmp = model.MasterAmountFlow{ + Uid: v.Uid, + Time: time.Now(), + BeforeAmount: oldAmount, + Amount: oldLastMonthAmount, + AfterAmount: v.Amount, + Platform: "playlet", + Oid: utils.IntToStr(v.Id), + Title: "短剧上月结算佣金到账", + FlowType: "last_month_playlet_settle", + IncomeType: 0, + ExtendUid: master.ExtendUid, + } + masterAmountFlowDb := db.MasterAmountFlowDb{} + masterAmountFlowDb.Set() + masterAmountFlowDb.MasterAmountFlowInsert(&tmp) + + var tmpLastMonth = model.MasterLastMonthAmountFlow{ + Uid: v.Uid, + Time: time.Now(), + BeforeAmount: oldLastMonthAmount, + Amount: oldLastMonthAmount, + AfterAmount: v.LastMonthAmount, + Platform: "playlet", + Oid: utils.IntToStr(v.Id), + Title: "短剧上月结算佣金转到余额", + FlowType: "last_month_playlet_settle", + IncomeType: 1, + ExtendUid: master.ExtendUid, + } + masterLastMonthAmountFlowDb := db.MasterLastMonthAmountFlowDb{} + masterLastMonthAmountFlowDb.Set() + masterLastMonthAmountFlowDb.MasterLastMonthAmountFlowInsert(&tmpLastMonth) + + } +} diff --git a/app/task/svc/svc_playlet_adv_order.go b/app/task/svc/svc_playlet_adv_order.go index 1b2055c..95aed47 100644 --- a/app/task/svc/svc_playlet_adv_order.go +++ b/app/task/svc/svc_playlet_adv_order.go @@ -52,8 +52,8 @@ func PlayletAdvOrder() { time.Sleep(time.Microsecond * 500) // 等待500毫秒 //获取订单 arg := map[string]interface{}{ - "start": time.Unix(beginTime, 0).Format("2006-01-02 15:04:05"), - "end": time.Unix(endTime, 0).Format("2006-01-02 15:04:05"), + "start": time.Unix(beginTime, 0).Format("2006-01-02"), + "end": time.Unix(endTime, 0).Format("2006-01-02"), "page_size": pageSize, "page_index": pageNo, } @@ -101,7 +101,10 @@ func PlayletAdvOrderYesterday(hours int, runtimeStr string) { syscfgDb := db.MasterListCfgDb{} syscfgDb.Set() playletVideoOrderYesterdayRuntime := syscfgDb.MasterListCfgGetOneData(uid, runtimeStr) - if utils.TimeStdParseUnix(playletVideoOrderYesterdayRuntime) > timeRange["start"] { + t := time.Now() + stime := time.Date(t.Year(), t.Month(), t.Day(), hours, 0, 0, 0, t.Location()) + + if utils.TimeStdParseUnix(playletVideoOrderYesterdayRuntime) > stime.Unix() { return } var ( @@ -115,12 +118,12 @@ func PlayletAdvOrderYesterday(hours int, runtimeStr string) { time.Sleep(time.Microsecond * 500) // 等待500毫秒 //获取订单 arg := map[string]interface{}{ - "start": time.Unix(beginTime, 0).Format("2006-01-02 15:04:05"), - "end": time.Unix(endTime, 0).Format("2006-01-02 15:04:05"), + "start": time.Unix(beginTime, 0).Format("2006-01-02"), + "end": time.Unix(endTime, 0).Format("2006-01-02"), "page_size": pageSize, "page_index": pageNo, } - count := getVideoOrder(uid, arg) + count := getAdvOrder(uid, arg) if count == 0 { break } @@ -146,6 +149,10 @@ func PlayletAdvOrderMonth() { if day < 5 { return } + hour := time.Now().Hour() + if hour < 3 { + return + } syscfgDb := db.MasterListCfgDb{} syscfgDb.Set() //上次开始的时间 @@ -160,14 +167,15 @@ func PlayletAdvOrderMonth() { syscfgDb.MasterListCfgUpdate(uid, keyIsEnd, "") runtime = time.Unix(timeRange["start"], 0).Format("2006-01-02 15:04:05") } + syscfgDb.MasterListCfgUpdate(uid, keyStart, time.Now().Format("2006-01-02 15:04:05")) //当前是否结束了 isEnd := syscfgDb.MasterListCfgGetOneData(uid, keyIsEnd) if isEnd == "1" { return } var ( - beginTime int64 = utils.TimeStdParseUnix(runtime) - 86400 - endTime int64 = utils.TimeStdParseUnix(runtime) + beginTime int64 = utils.TimeStdParseUnix(runtime) + endTime int64 = utils.TimeStdParseUnix(runtime) + 86400 pageNo int = 1 pageSize int = 200 ) @@ -177,8 +185,8 @@ func PlayletAdvOrderMonth() { time.Sleep(time.Microsecond * 500) // 等待500毫秒 //获取订单 arg := map[string]interface{}{ - "start": time.Unix(beginTime, 0).Format("2006-01-02 15:04:05"), - "end": time.Unix(endTime, 0).Format("2006-01-02 15:04:05"), + "start": time.Unix(beginTime, 0).Format("2006-01-02"), + "end": time.Unix(endTime, 0).Format("2006-01-02"), "page_size": pageSize, "page_index": pageNo, } @@ -198,6 +206,12 @@ func PlayletAdvOrderMonth() { return } +/*** +注意 广告点击pv,uv每小时统计一次,结算金额将于次日,投流平台更新数据后更新 +建议 所有统计数据:每小时在整点拉取当日统计,在次日凌晨1点后拉取一次昨日所有统计数据。金额数据, +建议在次日12:00后拉取后更新,可以将channel,source_id,created_time联合作为唯一索引, +如果遇到数据更新不及时,请联系客服。 +*/ func getAdvOrder(uids string, arg map[string]interface{}) int { list := make([]map[string]string, 0) token := GetTpdarenToken(uids) @@ -215,19 +229,21 @@ func getAdvOrder(uids string, arg map[string]interface{}) int { dataList := make([]md.PlayletAdvOrder, 0) json.Unmarshal([]byte(data), &dataList) - sysCfgDb := db.MasterListCfgDb{} + sysCfgDb := db.SysCfgDb{} sysCfgDb.Set() - playletKuaishouBili := sysCfgDb.MasterListCfgGetOneData(uids, "adv_kuaishou_bili") - playletDouyinBili := sysCfgDb.MasterListCfgGetOneData(uids, "adv_douyin_bili") - playletChannelBili := sysCfgDb.MasterListCfgGetOneData(uids, "adv_channel_bili") + playletKuaishouBili := sysCfgDb.SysCfgGetOneData("adv_kuaishou_bili") + playletDouyinBili := sysCfgDb.SysCfgGetOneData("adv_douyin_bili") + playletChannelBili := sysCfgDb.SysCfgGetOneData("adv_channel_bili") var biliMap = map[string]string{ "kuaishou": playletKuaishouBili, "douyin": playletDouyinBili, "channel": playletChannelBili, } - zyPlayletKuaishouBili := sysCfgDb.MasterListCfgGetOneData(uids, "zy_adv_kuaishou_bili") - zyPlayletDouyinBili := sysCfgDb.MasterListCfgGetOneData(uids, "zy_adv_douyin_bili") - zyPlayletChannelBili := sysCfgDb.MasterListCfgGetOneData(uids, "zy_adv_channel_bili") + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + zyPlayletKuaishouBili := masterListCfgDb.MasterListCfgGetOneData(uids, "zy_adv_kuaishou_bili") + zyPlayletDouyinBili := masterListCfgDb.MasterListCfgGetOneData(uids, "zy_adv_douyin_bili") + zyPlayletChannelBili := masterListCfgDb.MasterListCfgGetOneData(uids, "zy_adv_channel_bili") var zyBiliMap = map[string]string{ "kuaishou": zyPlayletKuaishouBili, "douyin": zyPlayletDouyinBili, @@ -257,7 +273,13 @@ func getAdvOrder(uids string, arg map[string]interface{}) int { zyBili := zyBiliMap[v.Channel] platformFee := utils.Float64ToStr(utils.StrToFloat64(money) * utils.StrToFloat64(bili) / 100) zyFee := utils.Float64ToStr(utils.StrToFloat64(money) * utils.StrToFloat64(zyBili) / 100) - commission := utils.Float64ToStr(utils.StrToFloat64(money) - utils.StrToFloat64(platformFee) - utils.StrToFloat64(zyFee)) + commission := "0" + if utils.StrToFloat64(money) > 0 { + commission = utils.Float64ToStr(utils.StrToFloat64(money) - utils.StrToFloat64(platformFee) - utils.StrToFloat64(zyFee)) + } + if utils.StrToFloat64(commission) < 0 { + commission = "0" + } var tmp = model.PlayletSaleOrder{ Uid: mid, SubUid: utils.StrToInt(uid), diff --git a/app/task/svc/svc_playlet_order_settle.go b/app/task/svc/svc_playlet_order_settle.go new file mode 100644 index 0000000..2330dc5 --- /dev/null +++ b/app/task/svc/svc_playlet_order_settle.go @@ -0,0 +1,93 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/utils" + "applet/app/utils/cache" + "fmt" + "time" +) + +func PlayletOrderSettle() { + day := time.Now().Day() + if day < 5 { + return + } + month := utils.GetTimeRange("current_month") + fmt.Println(month) + arg := map[string]string{ + "status": "订单结算", + "sort": "id desc", + "is_to_settle": "1", + "to_settle_time": time.Unix(month["start"], 0).Format("2006-01-02 15:04:05"), + "p": "1", + "size": "100", + } + playletSaleOrderDb := db.PlayletSaleOrderDb{} + playletSaleOrderDb.Set() + order := playletSaleOrderDb.GetPlayletVideoOrderList(arg) + if len(order) == 0 { + return + } + + for _, v := range order { + // 加锁 防止并发提取 + mutexKey := fmt.Sprintf("playlet_order_settle:%s", v.CustomOid) + withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 1800, "NX") + if err != nil { + continue + } + if withdrawAvailable != "OK" { + continue + } + if v.SettleTime > 0 { + continue + } + //加到上月结算 + if v.Uid == "" || v.Uid == "0" { + continue + } + masterDb := db.MasterDb{} + masterDb.Set() + master := masterDb.GetMaster(v.Uid) + if master == nil { + continue + } + masterAmountDb := db.MasterAmountDb{} + masterAmountDb.Set() + amount := masterAmountDb.GetMasterAmount(utils.IntToStr(master.Id), "playlet") + if amount == nil { + continue + } + if utils.StrToFloat64(v.Commission) <= 0 { + v.SettleTime = int(time.Now().Unix()) + playletSaleOrderDb.PlayletVideoOrderUpdate(v.Id, &v) + continue + } + oldAmount := amount.LastMonthAmount + amount.LastMonthAmount = utils.Float64ToStr(utils.StrToFloat64(amount.LastMonthAmount) + utils.StrToFloat64(v.Commission)) + update := masterAmountDb.MasterAmountUpdate(master.Id, amount) + if update == false { + continue + } + var tmp = model.MasterLastMonthAmountFlow{ + Uid: utils.IntToStr(master.Id), + Time: time.Now(), + BeforeAmount: oldAmount, + Amount: v.Commission, + AfterAmount: amount.LastMonthAmount, + Platform: "playlet", + Oid: v.Oid, + Title: "短剧订单结算", + FlowType: "playlet_settle", + ExtendUid: master.ExtendUid, + } + masterLastMonthAmountFlowDb := db.MasterLastMonthAmountFlowDb{} + masterLastMonthAmountFlowDb.Set() + masterLastMonthAmountFlowDb.MasterLastMonthAmountFlowInsert(&tmp) + v.SettleTime = int(time.Now().Unix()) + playletSaleOrderDb.PlayletVideoOrderUpdate(v.Id, &v) + } + return +} diff --git a/app/task/svc/svc_playlet_video_order.go b/app/task/svc/svc_playlet_video_order.go index fd39952..fb5e21a 100644 --- a/app/task/svc/svc_playlet_video_order.go +++ b/app/task/svc/svc_playlet_video_order.go @@ -111,6 +111,7 @@ func PlayletVideoOrderYesterDay() { "end": time.Unix(endTime, 0).Format("2006-01-02 15:04:05"), "page_size": pageSize, "page_index": pageNo, + "status": 2, } count := getVideoOrder(uid, arg) if count == 0 { @@ -138,6 +139,10 @@ func PlayletVideoOrderMonth() { if day < 5 { return } + hour := time.Now().Hour() + if hour < 3 { + return + } syscfgDb := db.MasterListCfgDb{} syscfgDb.Set() //上次开始的时间 @@ -152,14 +157,16 @@ func PlayletVideoOrderMonth() { syscfgDb.MasterListCfgUpdate(uid, keyIsEnd, "") runtime = time.Unix(timeRange["start"], 0).Format("2006-01-02 15:04:05") } + syscfgDb.MasterListCfgUpdate(uid, keyStart, time.Now().Format("2006-01-02 15:04:05")) + //当前是否结束了 isEnd := syscfgDb.MasterListCfgGetOneData(uid, keyIsEnd) if isEnd == "1" { return } var ( - beginTime int64 = utils.TimeStdParseUnix(runtime) - 86400 - endTime int64 = utils.TimeStdParseUnix(runtime) + beginTime int64 = utils.TimeStdParseUnix(runtime) + endTime int64 = utils.TimeStdParseUnix(runtime) + 86400 pageNo int = 1 pageSize int = 200 ) @@ -189,6 +196,11 @@ func PlayletVideoOrderMonth() { syscfgDb.MasterListCfgUpdate(uid, key, time.Unix(endTime, 0).Format("2006-01-02 15:04:05")) return } + +/*** +注意 在选择status为2退款时,start,end的筛选字段将是退款时间,时间范围最大为30天 +建议 所有订单:实时订单,延迟最多1分钟内。退款订单:建议每日凌晨1点后拉取一次昨日退款订单。 +*/ func getVideoOrder(uids string, arg map[string]interface{}) int { list := make([]map[string]string, 0) token := GetTpdarenToken(uids) @@ -206,19 +218,21 @@ func getVideoOrder(uids string, arg map[string]interface{}) int { dataList := make([]md.PlayletVideoOrder, 0) json.Unmarshal([]byte(data), &dataList) - sysCfgDb := db.MasterListCfgDb{} + sysCfgDb := db.SysCfgDb{} sysCfgDb.Set() - playletKuaishouBili := sysCfgDb.MasterListCfgGetOneData(uids, "playlet_kuaishou_bili") - playletDouyinBili := sysCfgDb.MasterListCfgGetOneData(uids, "playlet_douyin_bili") - playletChannelBili := sysCfgDb.MasterListCfgGetOneData(uids, "playlet_channel_bili") + playletKuaishouBili := sysCfgDb.SysCfgGetOneData("playlet_kuaishou_bili") + playletDouyinBili := sysCfgDb.SysCfgGetOneData("playlet_douyin_bili") + playletChannelBili := sysCfgDb.SysCfgGetOneData("playlet_channel_bili") var biliMap = map[string]string{ "kuaishou": playletKuaishouBili, "douyin": playletDouyinBili, "channel": playletChannelBili, } - zyPlayletKuaishouBili := sysCfgDb.MasterListCfgGetOneData(uids, "zy_playlet_kuaishou_bili") - zyPlayletDouyinBili := sysCfgDb.MasterListCfgGetOneData(uids, "zy_playlet_douyin_bili") - zyPlayletChannelBili := sysCfgDb.MasterListCfgGetOneData(uids, "zy_playlet_channel_bili") + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + zyPlayletKuaishouBili := masterListCfgDb.MasterListCfgGetOneData(uids, "zy_playlet_kuaishou_bili") + zyPlayletDouyinBili := masterListCfgDb.MasterListCfgGetOneData(uids, "zy_playlet_douyin_bili") + zyPlayletChannelBili := masterListCfgDb.MasterListCfgGetOneData(uids, "zy_playlet_channel_bili") var zyBiliMap = map[string]string{ "kuaishou": zyPlayletKuaishouBili, "douyin": zyPlayletDouyinBili, @@ -246,7 +260,13 @@ func getVideoOrder(uids string, arg map[string]interface{}) int { zyBili := zyBiliMap[v.Channel] platformFee := utils.Float64ToStr(utils.StrToFloat64(money) * utils.StrToFloat64(bili) / 100) zyFee := utils.Float64ToStr(utils.StrToFloat64(money) * utils.StrToFloat64(zyBili) / 100) - commission := utils.Float64ToStr(utils.StrToFloat64(money) - utils.StrToFloat64(platformFee) - utils.StrToFloat64(zyFee)) + commission := "0" + if utils.StrToFloat64(money) > 0 { + commission = utils.Float64ToStr(utils.StrToFloat64(money) - utils.StrToFloat64(platformFee) - utils.StrToFloat64(zyFee)) + } + if utils.StrToFloat64(commission) < 0 { + commission = "0" + } var tmp = model.PlayletSaleOrder{ Uid: mid, SubUid: utils.StrToInt(uid), diff --git a/app/task/task_master_month_settle.go b/app/task/task_master_month_settle.go new file mode 100644 index 0000000..2b576c4 --- /dev/null +++ b/app/task/task_master_month_settle.go @@ -0,0 +1,22 @@ +package task + +import ( + "applet/app/task/svc" + "math/rand" + "time" +) + +// +func taskMasterMonthSettle() { + for { + if len(ch) > workerNum { + time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) + } else { + goto START + } + } +START: + ch <- 1 + svc.MasterMonthSettle() + <-ch +} diff --git a/app/task/task_playlet_order_settle.go b/app/task/task_playlet_order_settle.go new file mode 100644 index 0000000..860612e --- /dev/null +++ b/app/task/task_playlet_order_settle.go @@ -0,0 +1,22 @@ +package task + +import ( + "applet/app/task/svc" + "math/rand" + "time" +) + +// +func taskPlayletOrderSettle() { + for { + if len(ch) > workerNum { + time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) + } else { + goto START + } + } +START: + ch <- 1 + svc.PlayletOrderSettle() + <-ch +} diff --git a/app/utils/auth.go b/app/utils/auth.go index 7b95682..556e32a 100644 --- a/app/utils/auth.go +++ b/app/utils/auth.go @@ -9,32 +9,60 @@ import ( ) // GenToken 生成JWT -func GenToken(admId int, username string) (string, error) { +func GenToken(masterId string) (aToken, rToken string, err error) { // 创建一个我们自己的声明 - c := auth.JWTUser{ - AdmId: admId, - Username: username, - StandardClaims: jwt.StandardClaims{ + c := auth.JWTMaster{ + masterId, + jwt.StandardClaims{ ExpiresAt: time.Now().Add(auth.TokenExpireDuration).Unix(), // 过期时间 - Issuer: "zyos", // 签发人 + Issuer: "zyos_zhimeng", // 签发人 }, } // 使用指定的签名方法创建签名对象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) // 使用指定的secret签名并获得完整的编码后的字符串token - return token.SignedString(auth.Secret) + aToken, err = token.SignedString(auth.Secret) + if err != nil { + return "", "", err + } + + // rToken 生成 + rc := auth.JWTMaster{ + masterId, + jwt.StandardClaims{ + ExpiresAt: time.Now().Add(auth.RefreshTokenExpireDuration).Unix(), // 过期时间 + Issuer: "zyos_zhimeng", // 签发人 + }, + } + rToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, rc).SignedString(auth.RSecret) + return } // ParseToken 解析JWT -func ParseToken(tokenString string) (*auth.JWTUser, error) { +func ParseToken(tokenString string) (*auth.JWTMaster, error) { // 解析token - token, err := jwt.ParseWithClaims(tokenString, &auth.JWTUser{}, func(token *jwt.Token) (i interface{}, err error) { + token, err := jwt.ParseWithClaims(tokenString, &auth.JWTMaster{}, func(token *jwt.Token) (i interface{}, err error) { return auth.Secret, nil }) if err != nil { return nil, err } - if claims, ok := token.Claims.(*auth.JWTUser); ok && token.Valid { // 校验token + if claims, ok := token.Claims.(*auth.JWTMaster); ok && token.Valid { // 校验token + return claims, nil + } + return nil, errors.New("invalid token") +} + +// ParseRToken 解析JWT +func ParseRToken(tokenString string) (*auth.JWTMaster, error) { + // 解析token + token, err := jwt.ParseWithClaims(tokenString, &auth.JWTMaster{}, func(token *jwt.Token) (i interface{}, err error) { + return auth.RSecret, nil + }) + if err != nil { + return nil, err + } + if claims, ok := token.Claims.(*auth.JWTMaster); ok && token.Valid { // 校验token return claims, nil } return nil, errors.New("invalid token") diff --git a/app/utils/cache/redis.go b/app/utils/cache/redis.go index de3be89..3c4b914 100644 --- a/app/utils/cache/redis.go +++ b/app/utils/cache/redis.go @@ -48,7 +48,6 @@ func NewRedis(addr string) { Wait: true, Dial: func() (redigo.Conn, error) { c, err := redigo.Dial("tcp", addr, - redigo.DialPassword(redisPassword), redigo.DialConnectTimeout(redisDialTTL), redigo.DialReadTimeout(redisReadTTL), redigo.DialWriteTimeout(redisWriteTTL), diff --git a/app/utils/time.go b/app/utils/time.go index 6860a57..9892463 100644 --- a/app/utils/time.go +++ b/app/utils/time.go @@ -168,11 +168,11 @@ func GetTimeRange(s string) map[string]int64 { // 明天 0点 etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location()) case "current_month": - stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) + stime = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location()) etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location()) case "last_month": - stime = time.Date(t.Year(), t.Month()-1, 0, 0, 0, 0, 0, t.Location()) - etime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) + stime = time.Date(t.Year(), t.Month()-1, 1, 0, 0, 0, 0, t.Location()) + etime = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location()) } return map[string]int64{ diff --git a/app/utils/xls.go b/app/utils/xls.go new file mode 100644 index 0000000..4b0318a --- /dev/null +++ b/app/utils/xls.go @@ -0,0 +1,36 @@ +package utils + +import ( + "bytes" + "fmt" + "github.com/360EntSecGroup-Skylar/excelize" + "github.com/gin-gonic/gin" + "io/ioutil" +) + +func Output(c *gin.Context, name string, data map[string]string) string { + //创建excel文件 + xlsx := excelize.NewFile() + //创建新表单 + index := xlsx.NewSheet(name) + for k, v := range data { + //设置单元格的值 + xlsx.SetCellValue(name, k, v) + } + //设置默认打开的表单 + xlsx.SetActiveSheet(index) + ////保存文件到指定路径 + //err := xlsx.SaveAs("./" + name + ".xlsx") + //if err != nil { + // log.Fatal(err) + //} + //_ = file.Save(fileName) + c.Header("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name+".xlsx")) + c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + var buffer bytes.Buffer + _ = xlsx.Write(&buffer) + r := bytes.NewReader(buffer.Bytes()) + fSrc, _ := ioutil.ReadAll(r) + str := "data:application/vnd.ms-excel;base64," + Base64RawStdEncode(string(fSrc)) + return str +} diff --git a/cmd_db.bat b/cmd_db.bat index 7a9e8d5..324f997 100644 --- a/cmd_db.bat +++ b/cmd_db.bat @@ -12,7 +12,7 @@ if "%one%" NEQ "" ( set BasePath="./" set DBUSER="root" set DBPSW="Fnuo123com@" -set DBNAME="fnuoos_test1" +set DBNAME="zhi_meng" set DBHOST="119.23.182.117" set DBPORT="3306" diff --git a/etc/cfg.yml b/etc/cfg.yml index 5dadd9f..44c8133 100644 --- a/etc/cfg.yml +++ b/etc/cfg.yml @@ -6,7 +6,7 @@ local: true # 服务器参数 srv_addr: ':5600' # 缓存 -redis_addr: '47.108.198.174:6379' +redis_addr: '120.24.28.6:32572' app_comm: # 本模块外网地址 @@ -24,6 +24,17 @@ db: max_idle_conns: 100 path: 'tmp/%s.log' +zhimeng_db: + host: '119.23.182.117:3306' + name: 'zhi_meng' + user: 'root' + psw: 'Fnuo123com@' + show_log: true + max_lifetime: 30 + max_open_conns: 100 + max_idle_conns: 100 + path: 'tmp/%s.log' + # 日志 log: app_name: 'applet' @@ -36,3 +47,9 @@ log: file_max_size: 256 file_max_age: 1 file_name: 'debug.log' + +# 连接ElasticSearch +es: + url: 'http://120.55.48.175:9200' + user: 'elastic' + pwd: 'fnuo123' \ No newline at end of file diff --git a/etc/task.yml b/etc/task.yml index 8d83d52..8d98605 100644 --- a/etc/task.yml +++ b/etc/task.yml @@ -5,6 +5,10 @@ local: true # 缓存 redis_addr: '120.24.28.6:32572' +redis_addr_second: + addr: '120.24.28.6:32572' + pwd: '' + # 数据库 db: host: '119.23.182.117:3306' diff --git a/go.mod b/go.mod index c2724a3..e26ccf7 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.15 require ( code.fnuoos.com/go_rely_warehouse/zyos_go_es.git v1.0.1-0.20230707081910-52e70aa52998 code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git v1.1.21-0.20230703061209-fc6ac71cc155 + github.com/360EntSecGroup-Skylar/excelize v1.4.1 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 github.com/boombuler/barcode v1.0.1 github.com/dchest/uniuri v1.2.0 @@ -19,6 +20,8 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/gomodule/redigo v2.0.0+incompatible github.com/makiuchi-d/gozxing v0.1.1 + github.com/mcuadros/go-defaults v1.2.0 + github.com/qiniu/api.v7/v7 v7.8.2 github.com/robfig/cron/v3 v3.0.1 github.com/sony/sonyflake v1.1.0 github.com/syyongx/php2go v0.9.7