package http import ( "bytes" "encoding/csv" "fmt" "io/ioutil" "net/http" "strconv" "time" "go-common/app/admin/main/member/model" "go-common/library/ecode" "go-common/library/log" bm "go-common/library/net/http/blademaster" "github.com/pkg/errors" ) func realnameList(ctx *bm.Context) { var ( arg = &model.ArgRealnameList{} list []*model.RespRealnameApply total int err error ) if err = ctx.Bind(arg); err != nil { return } if arg.PN <= 0 { arg.PN = 1 } if arg.PS <= 0 || arg.PS > 100 { arg.PS = 10 } // 没有指定实名认证申请状态State,默认查询所有 if arg.State == "" { arg.State = model.RealnameApplyStateAll } // 如果没有使用 mid || card 则取默认7天前作为 TSFrom if arg.MID == 0 && arg.Card == "" { if arg.TSFrom <= 0 { arg.TSFrom = time.Now().Add(-time.Hour * 24 * 7).Unix() } } // 如果使用 mid 或 card 进行查询,则查询所有时间段对应的数据 if arg.MID != 0 || arg.Card != "" { arg.TSFrom = 0 arg.TSTo = 0 } if list, total, err = svc.RealnameList(ctx, arg); err != nil { ctx.JSON(nil, err) return } res := map[string]interface{}{ "list": list, "page": map[string]int{ "num": arg.PN, "size": arg.PS, "total": total, }, } ctx.JSON(res, nil) } func realnamePendingList(ctx *bm.Context) { var ( arg = &model.ArgRealnamePendingList{} list []*model.RespRealnameApply total int err error ) if err = ctx.Bind(arg); err != nil { return } if arg.PN <= 0 { arg.PN = 1 } if arg.PS <= 0 || arg.PS > 100 { arg.PS = 10 } if list, total, err = svc.RealnamePendingList(ctx, arg); err != nil { ctx.JSON(nil, err) return } res := map[string]interface{}{ "list": list, "page": map[string]int{ "num": arg.PN, "size": arg.PS, "total": total, }, } ctx.JSON(res, nil) } func realnameAuditApply(ctx *bm.Context) { var ( arg = &model.ArgRealnameAuditApply{} adminName string adminID int64 data interface{} ok bool err error ) if err = ctx.Bind(arg); err != nil { return } // 驳回必须有reason if arg.Action == model.RealnameActionReject && arg.Reason == "" { ctx.JSON(nil, ecode.RequestErr) return } if data, ok = ctx.Get("username"); !ok { ctx.JSON(nil, ecode.AccessDenied) return } if adminName, ok = data.(string); !ok { ctx.JSON(nil, ecode.ServerErr) return } if data, ok = ctx.Get("uid"); !ok { ctx.JSON(nil, ecode.AccessDenied) return } if adminID, ok = data.(int64); !ok { ctx.JSON(nil, ecode.ServerErr) return } ctx.JSON(nil, svc.RealnameAuditApply(ctx, arg, adminName, adminID)) } func realnameReasonList(ctx *bm.Context) { var ( arg = &model.ArgRealnameReasonList{} list []string total int err error ) if err = ctx.Bind(arg); err != nil { return } if arg.PN <= 0 { arg.PN = 1 } if arg.PS <= 0 || arg.PS > 100 { arg.PS = 20 } if list, total, err = svc.RealnameReasonList(ctx, arg); err != nil { ctx.JSON(nil, err) return } res := map[string]interface{}{ "list": list, "page": map[string]int{ "num": arg.PN, "size": arg.PS, "total": total, }, } ctx.JSON(res, nil) } func realnameSetReason(ctx *bm.Context) { var ( arg = &model.ArgRealnameSetReason{} ) if err := ctx.Bind(arg); err != nil { return } ctx.JSON(nil, svc.RealnameSetReason(ctx, arg)) } func realnameImage(ctx *bm.Context) { var ( arg = &model.ArgRealnameImage{} img []byte err error ) if err = ctx.Bind(arg); err != nil { return } if img, err = svc.FetchRealnameImage(ctx, arg.Token); err != nil { ctx.JSON(nil, err) return } ctx.Bytes(http.StatusOK, http.DetectContentType(img), img) } func realnameImagePreview(ctx *bm.Context) { var ( arg = &model.ArgRealnameImagePreview{} img []byte err error ) if err = ctx.Bind(arg); err != nil { return } if arg.BorderSize <= 0 { arg.BorderSize = 1000 } if img, err = svc.RealnameImagePreview(ctx, arg.Token, arg.BorderSize); err != nil { ctx.JSON(nil, err) return } ctx.Bytes(http.StatusOK, http.DetectContentType(img), img) } func realnameSearchCard(ctx *bm.Context) { var ( arg = &model.ArgRealnameSearchCard{} err error ) if err = ctx.Bind(arg); err != nil { return } if len(arg.Cards) > 50 { err = ecode.RequestErr return } ctx.JSON(svc.RealnameSearchCard(ctx, arg.Cards, arg.CardType, arg.Country)) } func realnameUnbind(ctx *bm.Context) { var ( arg = &model.ArgMid{} adminName string adminID int64 data interface{} ok bool err error ) if err = ctx.Bind(arg); err != nil { return } if data, ok = ctx.Get("username"); !ok { ctx.JSON(nil, ecode.AccessDenied) return } if adminName, ok = data.(string); !ok { ctx.JSON(nil, ecode.ServerErr) return } if data, ok = ctx.Get("uid"); !ok { ctx.JSON(nil, ecode.AccessDenied) return } if adminID, ok = data.(int64); !ok { ctx.JSON(nil, ecode.ServerErr) return } ctx.JSON(nil, svc.RealnameUnbind(ctx, arg.Mid, adminName, adminID)) } func realnameExport(ctx *bm.Context) { arg := &model.ArgMids{} if err := ctx.Bind(arg); err != nil { return } if len(arg.Mid) > 1000 { ctx.JSON(nil, ecode.RequestErr) return } realnameExports, err := svc.RealnameExcel(ctx, arg.Mid) if err != nil { ctx.JSON(nil, err) return } data := make([][]string, 0, len(realnameExports)) data = append(data, []string{"用户uid", "用户名", "昵称", "姓名", "手机号", "证件类型", "证件号"}) for _, user := range realnameExports { fields := []string{ strconv.FormatInt(user.Mid, 10), user.UserID, user.Uname, user.Realname, user.Tel, model.CardTypeString(user.CardType), avoidescape(user.CardNum), } data = append(data, fields) } buf := bytes.NewBuffer(nil) w := csv.NewWriter(buf) for _, record := range data { if err := w.Write(record); err != nil { ctx.JSON(nil, err) return } } w.Flush() res := buf.Bytes() ctx.Writer.Header().Set("Content-Type", "application/csv") ctx.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.csv", "实名认证导出")) ctx.Writer.Write([]byte("\xEF\xBB\xBF")) // 写 UTF-8 的 BOM 头,别删,删了客服就找上门了 ctx.Writer.Write(res) } func avoidescape(in string) string { return fmt.Sprintf("%s,", in) } func realnameSubmit(ctx *bm.Context) { arg := &model.ArgRealnameSubmit{} if err := ctx.Bind(arg); err != nil { return } ctx.JSON(nil, svc.RealnameSubmit(ctx, arg)) } func realnameFileUpload(c *bm.Context) { arg := &model.ArgMid{} if err := c.Bind(arg); err != nil { return } mid := arg.Mid defer c.Request.Form.Del("img") // 防止日志不出现 c.Request.ParseMultipartForm(32 << 20) imgBytes, err := func() ([]byte, error) { img := c.Request.FormValue("img") if img != "" { log.Info("Succeeded to parse img file from form value: mid: %d, length: %d", mid, len(img)) return []byte(img), nil } log.Warn("Failed to parse img file from form value, fallback to form file: mid: %d", mid) f, _, err := c.Request.FormFile("img") if err != nil { return nil, errors.Wrapf(err, "parse img form file: mid: %d", mid) } defer f.Close() data, err := ioutil.ReadAll(f) if err != nil { return nil, errors.Wrapf(err, "read img form file: mid: %d", mid) } if len(data) <= 0 { return nil, errors.Wrapf(err, "form file data: mid: %d, length: %d", mid, len(data)) } log.Info("Succeeded to parse file from form file: mid: %d, length: %d", mid, len(data)) return data, nil }() if err != nil { log.Error("Failed to parse realname upload file: mid: %d: %+v", mid, err) c.JSON(nil, ecode.RequestErr) return } var resData struct { SRC string `json:"token"` } if resData.SRC, err = svc.RealnameFileUpload(c, arg.Mid, imgBytes); err != nil { log.Error("%+v", err) c.JSON(nil, err) return } c.JSON(resData, nil) }