go-common/app/admin/main/member/model/realname.go
2019-04-22 18:49:16 +08:00

613 lines
16 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package model
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"strconv"
"strings"
"time"
"go-common/app/admin/main/member/conf"
memmdl "go-common/app/service/main/member/model"
"go-common/library/log"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
// realname conf var
var (
RealnameSalt = "biliidentification@#$%^&*()(*&^%$#"
RealnameImgPrefix = "/idenfiles/"
RealnameImgSuffix = ".txt"
LogActionRealnameUnbind = "realname_unbind"
LogActionRealnameBack = "realname_back"
LogActionRealnameSubmit = "realname_submit"
RealnameManagerLogID = 251
)
type realnameChannel string
// RealnameChannle
const (
ChannelMain realnameChannel = "main"
ChannelAlipay realnameChannel = "alipay"
)
func (ch realnameChannel) DBChannel() uint8 {
switch ch {
case ChannelMain:
return 0
case ChannelAlipay:
return 1
}
return 0
}
type realnameAction string
// RealnameAction
const (
RealnameActionPass realnameAction = "pass"
RealnameActionReject realnameAction = "reject"
)
// RealnameCardType is.
type RealnameCardType string
const (
cardTypeIdentityCard RealnameCardType = "identity_card"
cardTypeForeignPassport RealnameCardType = "foreign_passport"
//Mainland Travel Permit for Hong Kong and Macao Residents
cardTypeHongkongMacaoPermit RealnameCardType = "hongkong_macao_travel_permit"
//Mainland travel permit for Taiwan residents
cardTypeTaiwanPermit RealnameCardType = "taiwan_travel_permit"
cardTypeChinaPassport RealnameCardType = "china_passport"
//Foreigner's Permanent Residence Card
cardTypeForeignerPermanentResidenceCard RealnameCardType = "foreigner_permanent_residence_card"
cardTypeForeignIdentityCard RealnameCardType = "foreign_identity_card"
)
// RealnameApplyStatus is.
type RealnameApplyStatus string
// RealnameApplyStatus
const (
RealnameApplyStateAll RealnameApplyStatus = "all"
RealnameApplyStatePending RealnameApplyStatus = "pending"
RealnameApplyStatePassed RealnameApplyStatus = "passed"
RealnameApplyStateRejective RealnameApplyStatus = "rejective"
RealnameApplyStateNone RealnameApplyStatus = "none"
)
// DBStatus is.
func (r RealnameApplyStatus) DBStatus() int {
switch r {
case RealnameApplyStatePending:
return 0
case RealnameApplyStatePassed:
return 1
case RealnameApplyStateRejective:
return 2
default:
return -1
}
}
// ArgRealnameList is.
type ArgRealnameList struct {
Channel realnameChannel `form:"channel" validate:"required"`
MID int64 `form:"mid"`
Card string `form:"card"`
CardType RealnameCardType `form:"card_type"`
Country int `form:"country"`
OPName string `form:"op_name"`
TSFrom int64 `form:"ts_from"`
TSTo int64 `form:"ts_to"`
State RealnameApplyStatus `form:"state"`
PS int `form:"ps"`
PN int `form:"pn"`
IsDesc bool `form:"is_desc"`
}
// DBCardType return card_type store in db
func (a *ArgRealnameList) DBCardType() int {
switch a.CardType {
case cardTypeIdentityCard:
return 0
case cardTypeForeignPassport:
return 1
case cardTypeHongkongMacaoPermit:
return 2
case cardTypeTaiwanPermit:
return 3
case cardTypeChinaPassport:
return 4
case cardTypeForeignerPermanentResidenceCard:
return 5
case cardTypeForeignIdentityCard:
return 6
default:
log.Warn("ArgRealnameList : %+v , unknown CardType", a)
return -1
}
}
// DBCountry return country store in db
func (a *ArgRealnameList) DBCountry() int {
if a.CardType == "" {
return -1
}
return a.Country
}
// DBState return state store in db
func (a *ArgRealnameList) DBState() int {
switch a.State {
case RealnameApplyStateAll:
return -1
case RealnameApplyStatePending:
return 0
case RealnameApplyStatePassed:
return 1
case RealnameApplyStateRejective:
return 2
case RealnameApplyStateNone:
return 3
default:
log.Warn("ArgRealnameList : %+v , unknown State", a)
return 0
}
}
// ArgRealnamePendingList is.
type ArgRealnamePendingList struct {
Channel realnameChannel `form:"channel" validate:"required"`
PS int `form:"ps"`
PN int `form:"pn"`
}
// ArgRealnameAuditApply is.
type ArgRealnameAuditApply struct {
ID int64 `form:"id" validate:"required"`
Channel realnameChannel `form:"channel" validate:"required"`
Action realnameAction `form:"action" validate:"required"`
Reason string `form:"reason"`
}
// DBChannel return channel store in db
func (a *ArgRealnameAuditApply) DBChannel() int {
switch a.Channel {
case ChannelMain:
return 0
case ChannelAlipay:
return 1
default:
log.Warn("ArgRealnameAuditApply : %+v , unknown Channel", a)
return 0
}
}
// ArgRealnameReasonList is.
type ArgRealnameReasonList struct {
PS int `form:"ps"`
PN int `form:"pn"`
}
// ArgRealnameSetReason is.
type ArgRealnameSetReason struct {
Reasons []string `form:"reasons,split"`
}
// ArgRealnameImage is.
type ArgRealnameImage struct {
Token string `form:"token" validate:"required"`
}
// ArgRealnameImagePreview is.
type ArgRealnameImagePreview struct {
ArgRealnameImage
BorderSize uint `form:"border_size"` // 图片最大边长度(缩放后)
}
// ArgRealnameSearchCard is.
type ArgRealnameSearchCard struct {
Cards []string `form:"cards,split" validate:"required"`
CardType int `form:"card_type"`
Country int `form:"card_type"`
}
// RespRealnameApply is.
type RespRealnameApply struct {
ID int64 `json:"id"`
Channel realnameChannel `json:"channel"`
MID int64 `json:"mid"`
Nickname string `json:"nickname"`
Times int `json:"times"`
CardType RealnameCardType `json:"card_type"`
Country int16 `json:"country"`
Card string `json:"card"`
Realname string `json:"realname"`
Level int32 `json:"level"`
IMGIDs []int64 `json:"-"`
IMGs []string `json:"imgs"`
State RealnameApplyStatus `json:"state"`
OPName string `json:"op_name"`
OPTS int64 `json:"op_ts"`
OPReason string `json:"op_reason"`
CreateTS int64 `json:"create_ts"`
}
// ParseDBMainApply parse realname_apply from db
func (r *RespRealnameApply) ParseDBMainApply(db *DBRealnameApply) {
var err error
r.ID = db.ID
r.Channel = ChannelMain
r.MID = db.MID
r.CardType = r.convertCardType(db.CardType)
r.Country = db.Country
if db.CardNum != "" {
if r.Card, err = CardDecrypt(db.CardNum); err != nil {
log.Error("%+v", err)
}
}
r.IMGIDs = append(r.IMGIDs, db.HandIMG, db.FrontIMG, db.BackIMG)
r.Realname = db.Realname
r.State = r.ParseStatus(db.Status)
r.OPName = db.Operator
r.OPTS = db.OperatorTime.Unix()
r.OPReason = db.Remark
r.CreateTS = db.CTime.Unix()
}
// ParseDBAlipayApply parse realname_alipay_apply from db
func (r *RespRealnameApply) ParseDBAlipayApply(db *DBRealnameAlipayApply) {
var err error
r.ID = db.ID
r.Channel = ChannelAlipay
r.MID = db.MID
r.CardType = cardTypeIdentityCard // identity_card
r.Country = 0 // china
if db.Card != "" {
if r.Card, err = CardDecrypt(db.Card); err != nil {
log.Error("%+v", err)
}
}
r.ParseDBApplyIMG(db.IMG)
r.Realname = db.Realname
r.State = r.ParseStatus(db.Status)
r.OPName = "alipay"
if db.Operator != "" {
r.OPName = db.Operator
}
r.OPTS = db.OperatorTime.Unix()
r.OPReason = db.Reason
r.CreateTS = db.CTime.Unix()
}
// ParseDBApplyIMG parse apply_img from db
func (r *RespRealnameApply) ParseDBApplyIMG(token string) {
r.IMGs = append(r.IMGs, imgURL(token))
}
// ParseMember parse member info from rpc call
func (r *RespRealnameApply) ParseMember(mem *memmdl.Member) {
r.Nickname = mem.Name
r.Level = mem.LevelInfo.Cur
}
func imgURL(token string) string {
token = strings.TrimPrefix(token, "/idenfiles/")
token = strings.TrimSuffix(token, ".txt")
return fmt.Sprintf(conf.Conf.Realname.ImageURLTemplate, token)
}
// ParseStatus parse status stored in db
func (r *RespRealnameApply) ParseStatus(status int) (s RealnameApplyStatus) {
switch status {
case 0:
return RealnameApplyStatePending
case 1:
return RealnameApplyStatePassed
case 2:
return RealnameApplyStateRejective
default:
log.Warn("RespRealnameApply parse status err , unknown apply status :%d", status)
return RealnameApplyStateNone
}
}
// ConvertCardType convert card_type from db to api
func (r *RespRealnameApply) convertCardType(cardType int8) (t RealnameCardType) {
switch cardType {
case 0:
return cardTypeIdentityCard
case 1:
return cardTypeForeignPassport
case 2:
return cardTypeHongkongMacaoPermit
case 3:
return cardTypeTaiwanPermit
case 4:
return cardTypeChinaPassport
case 5:
return cardTypeForeignerPermanentResidenceCard
case 6:
return cardTypeForeignIdentityCard
default:
log.Warn("RespRealnameApply parse card type err , unknown card type :%d", cardType)
return cardTypeIdentityCard
}
}
// DBRealnameInfo is.
type DBRealnameInfo struct {
ID int64 `gorm:"column:id"`
MID int64 `gorm:"column:mid"`
Channel uint8 `gorm:"column:channel"`
Realname string `gorm:"column:realname"`
Country int16 `gorm:"column:country"`
CardType int8 `gorm:"column:card_type"`
Card string `gorm:"column:card"`
CardMD5 string `gorm:"column:card_md5"`
Status int `gorm:"column:status"`
Reason string `gorm:"column:reason"`
CTime time.Time `gorm:"column:ctime"`
MTime time.Time `gorm:"column:mtime"`
}
// TableName is...
func (d *DBRealnameInfo) TableName() string {
return "realname_info"
}
// DBRealnameApply is.
type DBRealnameApply struct {
ID int64 `gorm:"column:id"`
MID int64 `gorm:"column:mid"`
Realname string `gorm:"column:realname"`
Country int16 `gorm:"column:country"`
CardType int8 `gorm:"column:card_type"`
CardNum string `gorm:"column:card_num"`
CardMD5 string `gorm:"column:card_md5"`
HandIMG int64 `gorm:"column:hand_img"`
FrontIMG int64 `gorm:"column:front_img"`
BackIMG int64 `gorm:"column:back_img"`
Status int `gorm:"column:status"`
Operator string `gorm:"column:operator"`
OperatorID int64 `gorm:"column:operator_id"`
OperatorTime time.Time `gorm:"column:operator_time"`
Remark string `gorm:"column:remark"`
RemarkStatus int8 `gorm:"column:remark_status"`
CTime time.Time `gorm:"column:ctime"`
MTime time.Time `gorm:"column:mtime"`
}
// TableName is...
func (d *DBRealnameApply) TableName() string {
return "realname_apply"
}
// DBRealnameAlipayApply is.
type DBRealnameAlipayApply struct {
ID int64 `gorm:"column:id"`
MID int64 `gorm:"column:mid"`
Realname string `gorm:"column:realname"`
Card string `gorm:"column:card"`
IMG string `gorm:"column:img"`
Status int `gorm:"column:status"`
Reason string `gorm:"column:reason"`
Bizno string `gorm:"column:bizno"`
Operator string `gorm:"column:operator"`
OperatorID int64 `gorm:"column:operator_id"`
OperatorTime time.Time `gorm:"column:operator_time"`
CTime time.Time `gorm:"column:ctime"`
MTime time.Time `gorm:"column:mtime"`
}
// TableName is...
func (d *DBRealnameAlipayApply) TableName() string {
return "realname_alipay_apply"
}
// IsPassed is...
func (d *DBRealnameApply) IsPassed() bool {
return d.Status == 1
}
// DBRealnameApplyIMG is.
type DBRealnameApplyIMG struct {
ID int64 `gorm:"column:id"`
IMGData string `gorm:"column:img_data"`
CTime time.Time `gorm:"column:ctime"`
MTime time.Time `gorm:"column:mtime"`
}
// TableName ...
func (d *DBRealnameApplyIMG) TableName() string {
return "realname_apply_img"
}
// DBRealnameConfig ...
type DBRealnameConfig struct {
ID int64 `gorm:"column:id"`
Key string `gorm:"column:key"`
Data string `gorm:"column:data"`
CTime time.Time `gorm:"column:ctime"`
MTime time.Time `gorm:"column:mtime"`
}
// TableName ...
func (d *DBRealnameConfig) TableName() string {
return "realname_config"
}
// CardDecrypt is
func CardDecrypt(data string) (text string, err error) {
var (
dataBytes = []byte(data)
decryptedData []byte
textBytes []byte
size int
)
decryptedData = make([]byte, base64.StdEncoding.DecodedLen(len(dataBytes)))
if size, err = base64.StdEncoding.Decode(decryptedData, dataBytes); err != nil {
err = errors.Wrapf(err, "base decode %s", data)
return
}
if textBytes, err = rsaDecrypt(decryptedData[:size]); err != nil {
err = errors.Wrapf(err, "rsa decrypt %s , data : %s", decryptedData, data)
return
}
text = string(textBytes)
return
}
func rsaDecrypt(text []byte) (content []byte, err error) {
block, _ := pem.Decode(conf.Conf.Realname.RsaPriv)
if block == nil {
err = errors.New("private key error")
return
}
var (
privateKey *rsa.PrivateKey
)
if privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
err = errors.WithStack(err)
return
}
if content, err = rsa.DecryptPKCS1v15(rand.Reader, privateKey, text); err != nil {
err = errors.WithStack(err)
return
}
return
}
// DBRealnameAuditLog is.
type DBRealnameAuditLog struct {
ID int64 `gorm:"column:id"`
MID int64 `gorm:"column:mid"`
AdminID int64 `gorm:"column:admin_id"`
AdminName string `gorm:"column:admin_name"`
Channel uint8 `gorm:"column:channel"`
FromState int `gorm:"column:from_state"`
ToState int `gorm:"column:to_state"`
CTime time.Time `gorm:"column:ctime"`
MTime time.Time `gorm:"column:mtime"`
}
// Tablename is.
func (d *DBRealnameAuditLog) Tablename() string {
return "realname_audit_log"
}
// Realname is.
type Realname struct {
State RealnameApplyStatus `json:"state"`
Channel realnameChannel `json:"moral"`
Card string `json:"card"`
CardType int8 `json:"card_type"`
Country int16 `json:"country"`
Realname string `json:"realname"`
Images []string `json:"images"`
}
// ParseDBApplyIMG parse apply_img from db
func (r *Realname) ParseDBApplyIMG(token string) {
r.Images = append(r.Images, imgURL(token))
}
// ParseInfo .
func (r *Realname) ParseInfo(info *DBRealnameInfo) {
switch info.Status {
case 0:
r.State = RealnameApplyStatePending
case 1:
r.State = RealnameApplyStatePassed
case 2:
r.State = RealnameApplyStateRejective
default:
log.Warn("Realname status err , unknown info status :%d", info.Status)
r.State = RealnameApplyStateNone
}
switch info.Channel {
case 0:
r.Channel = ChannelMain
case 1:
r.Channel = ChannelAlipay
default:
log.Warn("Realname channel err , unknown info channel :%d", info.Channel)
r.Channel = ChannelMain
}
r.Realname = info.Realname
r.CardType = info.CardType
r.Country = info.Country
var err error
var maskedCard string
if info.Card != "" && r.State == RealnameApplyStatePassed {
if r.Card, err = CardDecrypt(info.Card); err != nil {
log.Error("%+v", err)
}
var (
cStrs = strings.Split(r.Card, "")
)
if len(cStrs) > 0 {
if len(cStrs) == 1 {
maskedCard = "*"
} else if len(cStrs) > 5 {
maskedCard = cStrs[0] + strings.Repeat("*", len(cStrs)-3) + strings.Join(cStrs[len(cStrs)-2:], "")
} else {
maskedCard = cStrs[0] + strings.Repeat("*", len(cStrs)-1)
}
}
r.Card = maskedCard
}
}
// RealnameExport is.
type RealnameExport struct {
Mid int64 `json:"mid" gorm:"column:mid"`
UserID string `json:"userid" gorm:"column:userid"`
Uname string `json:"uname" gorm:"column:uname"`
Realname string `json:"realname" gorm:"column:realname"`
Tel string `json:"tel" gorm:"column:tel"`
CardType int8 `json:"card_type" gorm:"column:card_type"`
CardNum string `json:"card_num" gorm:"column:card_num"`
}
// PassportQueryByMidResult is.
type PassportQueryByMidResult struct {
Mid int64 `json:"mid"`
Name string `json:"name"`
Userid string `json:"userid"`
Email string `json:"email"`
Tel string `json:"tel"`
Jointime xtime.Time `json:"jointime"`
}
var _cardTypeToString = map[int8]string{
0: "身份证",
1: "护照(境外签发)",
2: "港澳居民来往内地通行证",
3: "台湾居民来往大陆通行证",
4: "护照(中国签发)",
5: "外国人永久居留证",
6: "其他国家或地区身份证",
}
// CardTypeString is
func CardTypeString(cardType int8) string {
typeString, ok := _cardTypeToString[cardType]
if !ok {
return strconv.FormatInt(int64(cardType), 10)
}
return typeString
}