package esign import ( "context" "encoding/json" "fmt" "strings" "hyapi-server/internal/domains/certification/enums" "hyapi-server/internal/domains/certification/ports" sharedesign "hyapi-server/internal/shared/esign" ) type Provider struct { client *sharedesign.Client } func NewProvider(client *sharedesign.Client) *Provider { return &Provider{client: client} } func (p *Provider) Platform() enums.SignPlatform { return enums.SignPlatformEsign } func (p *Provider) GenerateEnterpriseAuth(ctx context.Context, req *ports.EnterpriseAuthRequest) (*ports.AuthLinkResult, error) { _ = ctx res, err := p.client.GenerateEnterpriseAuth(&sharedesign.EnterpriseAuthRequest{ CompanyName: req.CompanyName, UnifiedSocialCode: req.UnifiedSocialCode, LegalPersonName: req.LegalPersonName, LegalPersonID: req.LegalPersonID, TransactorName: req.TransactorName, TransactorMobile: req.TransactorMobile, TransactorID: req.TransactorID, }) if err != nil { return nil, err } return &ports.AuthLinkResult{ AuthFlowID: res.AuthFlowID, AuthURL: res.AuthURL, AuthShortURL: firstNonEmpty(res.AuthShortURL, res.AuthURL), }, nil } func (p *Provider) QueryOrgVerified(ctx context.Context, req *ports.OrgIdentityQuery) (bool, error) { _ = ctx identity, err := p.client.QueryOrgIdentityInfo(&sharedesign.QueryOrgIdentityRequest{ OrgName: req.OrgName, OrgIDCardNum: req.OrgIdentNo, }) if err != nil { return false, err } return identity != nil && identity.Data.RealnameStatus == 1, nil } func (p *Provider) GenerateContractFile(ctx context.Context, req *ports.ContractGenerateRequest) (*ports.ContractFileResult, error) { _ = ctx components := map[string]string{ "jfqym": req.CompanyName, "jfqym2": req.CompanyName, "jfsqdb": req.AuthorizedRepName, "jftyshxydm": req.UnifiedSocialCode, "jflxdz": req.EnterpriseAddress, "xybh": req.AgreementNo, "qsrq1": req.SignDate, "qsrq3": req.SignDate, "qsrq2": req.SignDate, } res, err := p.client.FillTemplate(components) if err != nil { return nil, err } return &ports.ContractFileResult{ FileID: res.FileID, FileDownloadURL: res.FileDownloadUrl, }, nil } func (p *Provider) CreateSignFlow(ctx context.Context, req *ports.SignFlowCreateRequest) (*ports.SignFlowResult, error) { _ = ctx flowID, err := p.client.CreateSignFlow(&sharedesign.CreateSignFlowRequest{ FileID: req.FileID, SignerAccount: req.PartyAUSCC, SignerName: req.PartyAName, TransactorPhone: req.TransactorMobile, TransactorName: req.TransactorName, TransactorIDCardNum: req.TransactorID, }) if err != nil { return nil, err } if req.SkipActorURL { return &ports.SignFlowResult{SignFlowID: flowID}, nil } longURL, shortURL, err := p.client.GetSignURL(flowID, req.TransactorMobile, req.PartyAName) if err != nil { return nil, err } return &ports.SignFlowResult{ SignFlowID: flowID, SignURL: firstNonEmpty(longURL, shortURL), ShortURL: shortURL, }, nil } func (p *Provider) GetActorSignURL(ctx context.Context, req *ports.GetActorSignURLRequest) (*ports.ActorSignURLResult, error) { _ = ctx if req == nil || strings.TrimSpace(req.SignFlowID) == "" { return nil, fmt.Errorf("signFlowId 不能为空") } longURL, shortURL, err := p.client.GetSignURL(req.SignFlowID, req.TransactorMobile, req.PartyAName) if err != nil { return nil, err } return &ports.ActorSignURLResult{ SignFlowID: req.SignFlowID, EmbedURL: firstNonEmpty(longURL, shortURL), ShortURL: shortURL, }, nil } func (p *Provider) GetSignTaskPreviewURL(ctx context.Context, signFlowID string) (*ports.SignTaskPreviewURLResult, error) { _ = ctx // e签宝无独立预览接口:用已签/合同文件下载链作为预览源(前端用 PDF 打开) files, err := p.DownloadSignedFiles(ctx, signFlowID) if err != nil { return nil, err } if len(files) == 0 || strings.TrimSpace(files[0].DownloadURL) == "" { return nil, fmt.Errorf("未获取到可预览的合同文件") } return &ports.SignTaskPreviewURLResult{ SignFlowID: signFlowID, PreviewURL: files[0].DownloadURL, }, nil } func (p *Provider) QuerySignStatus(ctx context.Context, flowID string) (*ports.SignStatusResult, error) { _ = ctx detail, err := p.client.QuerySignFlowDetail(flowID) if err != nil { return nil, err } status := detail.Data.SignFlowStatus return &ports.SignStatusResult{ SignFlowID: flowID, Status: fmt.Sprintf("%d", status), Completed: status == 2, Rejected: status == 7, Expired: status == 5, Message: detail.Data.SignFlowDescription, }, nil } func (p *Provider) DownloadSignedFiles(ctx context.Context, flowID string) ([]*ports.SignedFile, error) { _ = ctx res, err := p.client.DownloadSignedFile(flowID) if err != nil { return nil, err } files := make([]*ports.SignedFile, 0, len(res.Data.Files)) for _, f := range res.Data.Files { files = append(files, &ports.SignedFile{DownloadURL: f.DownloadUrl}) } return files, nil } func (p *Provider) VerifyCallback(ctx context.Context, headers map[string]string, body []byte) error { _ = ctx _ = headers _ = body // e签宝现有回调走独立验签逻辑,此处保持兼容(由原 HandleEsignCallback 处理) return nil } func (p *Provider) ParseCallback(ctx context.Context, headers map[string]string, body []byte) (*ports.CallbackEvent, error) { _ = ctx _ = headers var raw map[string]interface{} _ = json.Unmarshal(body, &raw) action, _ := raw["action"].(string) ev := &ports.CallbackEvent{Event: action, Raw: raw} if action == "AUTH_PASS" { ev.AuthPassed = true } if action == "SIGN_FLOW_COMPLETE" || action == "SIGN_MISSON_COMPLETE" { ev.SignCompleted = true } return ev, nil } func firstNonEmpty(values ...string) string { for _, v := range values { if strings.TrimSpace(v) != "" { return v } } return "" } var _ ports.SignPlatformProvider = (*Provider)(nil)