소스 검색

feat: 无章时查询资质并获取制章页链接

新增 CompanySignQualificationsFor、CompanySealCreatePageURL、
IsSealNotFoundError 与 PortalURL,供业务侧引导用户先制章再静默授权。

Co-authored-by: Cursor <cursoragent@cursor.com>
郭铭泽 6 일 전
부모
커밋
8854057ea0
3개의 변경된 파일118개의 추가작업 그리고 0개의 파일을 삭제
  1. 5 0
      client.go
  2. 2 0
      errors.go
  3. 111 0
      seal.go

+ 5 - 0
client.go

@@ -40,6 +40,11 @@ func (c *Client) baseURL() string {
 	return strings.TrimRight(c.cfg.Address, "/")
 }
 
+// PortalURL 契约锁用户前台地址(制章、验证码登录)。
+func (c *Client) PortalURL() string {
+	return UserPortalURL(c.baseURL())
+}
+
 func (c *Client) authHeaders() map[string]string {
 	nonce := uuid.NewString()
 	timestamp := fmt.Sprintf("%d", time.Now().UnixMilli())

+ 2 - 0
errors.go

@@ -7,6 +7,8 @@ var (
 	ErrCompanyNotRegistered = errors.New("qiyuesuo: company not registered")
 	// ErrInvalidParams 必填参数缺失。
 	ErrInvalidParams = errors.New("qiyuesuo: invalid params")
+	// ErrSealCreatePageUnavailable 制章页面链接未返回(可能未开通接口制章)。
+	ErrSealCreatePageUnavailable = errors.New("qiyuesuo: seal create page unavailable")
 )
 
 type apiResponse struct {

+ 111 - 0
seal.go

@@ -0,0 +1,111 @@
+package qiyuesuosdk
+
+import (
+	"strconv"
+	"strings"
+
+	v2seal_request "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/v2seal/request"
+	v2seal_response "git.sxidc.com/student-physical-examination/contract_lock_sdk/model/v2seal/response"
+	"git.sxidc.com/student-physical-examination/contract_lock_sdk/model/common"
+)
+
+// CompanySignQualifications 法人单位签章资质(是否已有可用电子章等)。
+type CompanySignQualifications struct {
+	ElectronicSeal bool `json:"electronicSeal"`
+	SM2Cert        bool `json:"sm2Cert"`
+	RSACert        bool `json:"rsaCert"`
+}
+
+type companySignQualificationsResp struct {
+	apiResponse
+	Result CompanySignQualifications `json:"result"`
+}
+
+type sealCreateResp struct {
+	apiResponse
+	Result v2seal_response.V2SealCreateResponse `json:"result"`
+}
+
+// UserPortalURL 由开放平台 API 地址推导用户前台地址(制章/登录)。
+func UserPortalURL(apiAddress string) string {
+	addr := strings.TrimRight(apiAddress, "/")
+	if strings.Contains(addr, ":9182") {
+		return strings.Replace(addr, ":9182", ":9180", 1)
+	}
+	return addr
+}
+
+// CompanySignQualificationsFor 查询法人单位是否具备电子印章等签章资质。
+func (c *Client) CompanySignQualificationsFor(company CompanyLocateParams) (*CompanySignQualifications, error) {
+	companyReq, err := company.toCompanyRequest()
+	if err != nil {
+		return nil, err
+	}
+	var resp companySignQualificationsResp
+	if err := c.postJSON("/company/sign/qualifications", map[string]any{
+		"companyRequest": companyReq,
+	}, &resp); err != nil {
+		return nil, err
+	}
+	if err := resp.err(); err != nil {
+		return nil, err
+	}
+	return &resp.Result, nil
+}
+
+// CompanySealCreatePageURL 获取制作电子公章的页面链接(method=page)。
+func (c *Client) CompanySealCreatePageURL(company CompanyLocateParams, companyDisplayName, sealName, operatorMobile string) (string, error) {
+	if sealName == "" || operatorMobile == "" {
+		return "", ErrInvalidParams
+	}
+	displayName := companyDisplayName
+	if displayName == "" {
+		displayName = company.Name
+	}
+	comp := &common.Company{Name: displayName}
+	if company.RegisterNo != "" {
+		comp.RegisterNo = company.RegisterNo
+	}
+	if company.ID != "" {
+		if id, err := strconv.ParseInt(company.ID, 10, 64); err == nil {
+			comp.Id = &id
+		}
+	}
+	modify := true
+	req := v2seal_request.V2SealCreateRequest{
+		BusinessType:     "ELECTRONIC",
+		SealType:         "COMPANY",
+		Method:           "page",
+		Name:             sealName,
+		SealCategoryName: "公章",
+		Company:          comp,
+		OperatorInfo: &common.UserInfoRequest{
+			Mobile: operatorMobile,
+		},
+		Modify: &modify,
+	}
+	var resp sealCreateResp
+	if err := c.postJSON("/v2/seal/create", req, &resp); err != nil {
+		return "", err
+	}
+	if err := resp.err(); err != nil {
+		return "", err
+	}
+	url := resp.Result.PageUrl
+	if url == "" {
+		url = resp.Result.LocalPageUrl
+	}
+	if url == "" {
+		return "", ErrSealCreatePageUnavailable
+	}
+	return url, nil
+}
+
+// IsSealNotFoundError 静默授权时「查询的印章不存在」。
+func IsSealNotFoundError(err error) bool {
+	if err == nil {
+		return false
+	}
+	msg := err.Error()
+	return strings.Contains(msg, "查询的印章不存在") || strings.Contains(msg, "无可授权的印章")
+}