Files
hfb_sys/backend/internal/modules/realname/provider.go
T

101 lines
2.1 KiB
Go

package realname
import (
"context"
"crypto/rand"
"encoding/hex"
"errors"
"strings"
"time"
"hfb_sys/backend/pkg/crypto"
)
type Provider interface {
Name() string
Start(ctx context.Context, req StartRequest) (ProviderResult, error)
}
type StartRequest struct {
UserID uint64
Name string
IDNo string
}
type ProviderResult struct {
ProviderOrderNo string
Status string
MaskedName string
EncryptedName string // 加密的完整姓名
MaskedIDNo string
EncryptedIDNo string // 加密的完整身份证号
VerifiedAt *time.Time
FailReason string
}
type MockProvider struct{}
func NewMockProvider() *MockProvider {
return &MockProvider{}
}
func (p *MockProvider) Name() string {
return "mock"
}
func (p *MockProvider) Start(_ context.Context, req StartRequest) (ProviderResult, error) {
if strings.TrimSpace(req.Name) == "" || strings.TrimSpace(req.IDNo) == "" {
return ProviderResult{}, errors.New("name and id no are required")
}
orderNo, err := randomOrderNo()
if err != nil {
return ProviderResult{}, err
}
// 加密完整信息
encryptedName, err := crypto.Encrypt(req.Name)
if err != nil {
return ProviderResult{}, err
}
encryptedIDNo, err := crypto.Encrypt(req.IDNo)
if err != nil {
return ProviderResult{}, err
}
now := time.Now()
return ProviderResult{
ProviderOrderNo: orderNo,
Status: StatusVerified,
MaskedName: maskName(req.Name),
EncryptedName: encryptedName,
MaskedIDNo: maskIDNo(req.IDNo),
EncryptedIDNo: encryptedIDNo,
VerifiedAt: &now,
}, nil
}
func randomOrderNo() (string, error) {
buf := make([]byte, 8)
if _, err := rand.Read(buf); err != nil {
return "", err
}
return "mock_rn_" + hex.EncodeToString(buf), nil
}
func maskName(name string) string {
name = strings.TrimSpace(name)
if len([]rune(name)) <= 1 {
return name
}
runes := []rune(name)
return string(runes[0]) + strings.Repeat("*", len(runes)-1)
}
func maskIDNo(idNo string) string {
idNo = strings.TrimSpace(idNo)
if len(idNo) <= 8 {
return idNo
}
return idNo[:4] + strings.Repeat("*", len(idNo)-8) + idNo[len(idNo)-4:]
}