This commit is contained in:
2026-07-27 12:37:29 +08:00
parent dc9a98e893
commit 9429e4f6e0
20 changed files with 1066 additions and 61 deletions

View File

@@ -0,0 +1,89 @@
package entities
import (
"strings"
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
// FadadaCorpAuthRecord 法大大企业授权相关数据(与 certifications 分离,便于签署链路复用)
// open_corp_id企业对本应用授权后法大大分配的企业标识
type FadadaCorpAuthRecord struct {
ID string `json:"id" gorm:"primaryKey;type:varchar(36)"`
UserID string `json:"user_id" gorm:"type:varchar(36);not null;index;comment:用户ID"`
CertificationID string `json:"certification_id" gorm:"type:varchar(36);index;comment:关联认证记录ID"`
AppID string `json:"app_id" gorm:"type:varchar(32);index;comment:法大大应用AppId"`
CompanyName string `json:"company_name" gorm:"type:varchar(200);comment:企业名称"`
UnifiedSocialCode string `json:"unified_social_code" gorm:"column:unified_social_code;type:varchar(50);index;comment:统一社会信用代码(corpIdentNo)"`
ClientCorpID string `json:"client_corp_id" gorm:"column:client_corp_id;type:varchar(64);index;comment:应用内企业标识(clientCorpId)"`
OpenCorpID string `json:"open_corp_id" gorm:"column:open_corp_id;type:varchar(64);index;comment:法大大企业openCorpId"`
BindingStatus string `json:"binding_status" gorm:"type:varchar(32);comment:授权绑定状态 unauthorized/authorized"`
IdentStatus string `json:"ident_status" gorm:"type:varchar(32);comment:实名状态 unidentified/identified"`
AvailableStatus string `json:"available_status" gorm:"type:varchar(32);comment:启用状态 disable/enable"`
AuthScopes string `json:"auth_scopes" gorm:"type:text;comment:授权范围JSON数组字符串"`
Source string `json:"source" gorm:"type:varchar(64);comment:数据来源"`
CreatedAt time.Time `json:"created_at" gorm:"not null"`
UpdatedAt time.Time `json:"updated_at" gorm:"not null"`
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"`
}
func (FadadaCorpAuthRecord) TableName() string {
return "fadada_corp_auth_records"
}
func NewFadadaCorpAuthRecord(userID, certificationID, appID, companyName, uscc, clientCorpID string) *FadadaCorpAuthRecord {
now := time.Now()
return &FadadaCorpAuthRecord{
ID: uuid.New().String(),
UserID: strings.TrimSpace(userID),
CertificationID: strings.TrimSpace(certificationID),
AppID: strings.TrimSpace(appID),
CompanyName: strings.TrimSpace(companyName),
UnifiedSocialCode: strings.TrimSpace(uscc),
ClientCorpID: strings.TrimSpace(clientCorpID),
Source: "init",
CreatedAt: now,
UpdatedAt: now,
}
}
func (r *FadadaCorpAuthRecord) ApplyAuthStatus(
openCorpID, clientCorpID, bindingStatus, identStatus, availableStatus string,
authScopes []string,
source string,
) {
if r == nil {
return
}
if v := strings.TrimSpace(openCorpID); v != "" {
r.OpenCorpID = v
}
if v := strings.TrimSpace(clientCorpID); v != "" {
r.ClientCorpID = v
}
if v := strings.TrimSpace(bindingStatus); v != "" {
r.BindingStatus = v
}
if v := strings.TrimSpace(identStatus); v != "" {
r.IdentStatus = v
}
if v := strings.TrimSpace(availableStatus); v != "" {
r.AvailableStatus = v
}
if len(authScopes) > 0 {
r.AuthScopes = strings.Join(authScopes, ",")
}
if v := strings.TrimSpace(source); v != "" {
r.Source = v
}
r.UpdatedAt = time.Now()
}
func (r *FadadaCorpAuthRecord) IsAuthorized() bool {
return r != nil && strings.EqualFold(strings.TrimSpace(r.BindingStatus), "authorized") && strings.TrimSpace(r.OpenCorpID) != ""
}

View File

@@ -34,6 +34,25 @@ type OrgIdentityQuery struct {
ClientCorpID string
}
// CorpAuthStatusQuery 企业授权状态查询(法大大 /corp/gete签宝可返回未授权
type CorpAuthStatusQuery struct {
CorpIdentNo string // 统一社会信用代码
ClientCorpID string // 应用内企业标识
OpenCorpID string // 法大大 openCorpId
}
// CorpAuthStatusResult 企业授权状态
type CorpAuthStatusResult struct {
Supported bool // 当前平台是否支持主动查询授权状态
Found bool // 本应用下是否已有企业记录
Authorized bool // bindingStatus=authorized
Identified bool // identStatus=identified
OpenCorpID string
ClientCorpID string
BindingStatus string
IdentStatus string
}
// ContractGenerateRequest 合同模板填单
type ContractGenerateRequest struct {
AgreementNo string
@@ -121,6 +140,8 @@ type CallbackEvent struct {
SignRejected bool
SignFlowID string
AuthFlowID string
OpenCorpID string
ClientCorpID string
OrgName string
Raw map[string]interface{}
}
@@ -131,6 +152,8 @@ type SignPlatformProvider interface {
GenerateEnterpriseAuth(ctx context.Context, req *EnterpriseAuthRequest) (*AuthLinkResult, error)
QueryOrgVerified(ctx context.Context, req *OrgIdentityQuery) (bool, error)
// QueryCorpAuthStatus 查询企业是否已对本应用完成授权绑定(法大大:/corp/get bindingStatus
QueryCorpAuthStatus(ctx context.Context, req *CorpAuthStatusQuery) (*CorpAuthStatusResult, error)
GenerateContractFile(ctx context.Context, req *ContractGenerateRequest) (*ContractFileResult, error)
CreateSignFlow(ctx context.Context, req *SignFlowCreateRequest) (*SignFlowResult, error)

View File

@@ -0,0 +1,21 @@
package repositories
import (
"context"
"hyapi-server/internal/domains/certification/entities"
)
// FadadaCorpAuthRecordRepository 法大大企业授权数据仓储
type FadadaCorpAuthRecordRepository interface {
Create(ctx context.Context, record *entities.FadadaCorpAuthRecord) error
Update(ctx context.Context, record *entities.FadadaCorpAuthRecord) error
FindByID(ctx context.Context, id string) (*entities.FadadaCorpAuthRecord, error)
FindLatestByUserID(ctx context.Context, userID string) (*entities.FadadaCorpAuthRecord, error)
FindByCertificationID(ctx context.Context, certificationID string) (*entities.FadadaCorpAuthRecord, error)
FindByOpenCorpID(ctx context.Context, openCorpID string) (*entities.FadadaCorpAuthRecord, error)
FindByUnifiedSocialCode(ctx context.Context, uscc string) (*entities.FadadaCorpAuthRecord, error)
FindByClientCorpID(ctx context.Context, clientCorpID string) (*entities.FadadaCorpAuthRecord, error)
// UpsertByBizKey 按认证ID优先否则按 USCC/clientCorpId 合并写入
UpsertByBizKey(ctx context.Context, record *entities.FadadaCorpAuthRecord) error
}

View File

@@ -467,7 +467,9 @@ func (s *UserAggregateServiceImpl) CheckUnifiedSocialCodeExists(ctx context.Cont
return exists, nil
}
// CreateOrUpdateEnterpriseInfo 认证域专用:写入/覆盖企业信息
// CreateOrUpdateEnterpriseInfo 认证域专用:按两条链路写入企业信息
// - 新用户:尚无企业信息 → 创建
// - 重新认证:已有企业信息 → 覆盖更新
func (s *UserAggregateServiceImpl) CreateOrUpdateEnterpriseInfo(
ctx context.Context,
userID, companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress string,
@@ -476,19 +478,44 @@ func (s *UserAggregateServiceImpl) CreateOrUpdateEnterpriseInfo(
if err != nil {
return fmt.Errorf("用户不存在: %w", err)
}
if user.EnterpriseInfo == nil {
enterpriseInfo, err := entities.NewEnterpriseInfo(userID, companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress)
if err != nil {
return err
}
user.EnterpriseInfo = enterpriseInfo
} else {
err := user.EnterpriseInfo.UpdateEnterpriseInfo(companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress)
if err != nil {
return err
}
// 统一校验 USCC排除本人新用户创建与重新认证更新均适用
exists, err := s.CheckUnifiedSocialCodeExists(ctx, unifiedSocialCode, userID)
if err != nil {
return fmt.Errorf("检查统一社会信用代码失败: %w", err)
}
return s.SaveUser(ctx, user)
if exists {
return fmt.Errorf("统一社会信用代码已被其他用户使用")
}
if user.HasEnterpriseInfo() {
s.logger.Info("重新认证链路:更新已有企业信息",
zap.String("user_id", userID),
zap.String("unified_social_code", unifiedSocialCode),
zap.String("enterprise_info_id", user.EnterpriseInfo.ID),
)
if err := user.UpdateEnterpriseInfo(companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress); err != nil {
return fmt.Errorf("更新企业信息失败: %w", err)
}
if err := s.SaveUser(ctx, user); err != nil {
return fmt.Errorf("保存企业信息失败: %w", err)
}
s.logger.Info("重新认证链路:企业信息更新成功", zap.String("user_id", userID))
return nil
}
s.logger.Info("新用户认证链路:创建企业信息",
zap.String("user_id", userID),
zap.String("unified_social_code", unifiedSocialCode),
)
if err := user.CreateEnterpriseInfo(companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress); err != nil {
return fmt.Errorf("创建企业信息失败: %w", err)
}
if err := s.SaveUser(ctx, user); err != nil {
return fmt.Errorf("保存企业信息失败: %w", err)
}
s.logger.Info("新用户认证链路:企业信息创建成功", zap.String("user_id", userID))
return nil
}
// CompleteCertification 完成认证