Files
hyapi-server/internal/shared/fadada/corp_service.go
2026-07-21 15:53:29 +08:00

181 lines
5.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package fadada
import (
"fmt"
"net/url"
"strings"
)
// 默认授权范围:认证信息 + 后续签署所需能力
var defaultAuthScopes = []string{
"ident_info",
"seal_info",
"signtask_info",
"signtask_init",
"signtask_file",
"organization",
"template",
}
// GenerateEnterpriseAuth 获取企业认证/授权链接POST /corp/get-auth-url
// 文档见 1.mdcorpIdentType 置空由用户在页面选择组织类型。
func (c *Client) GenerateEnterpriseAuth(req *EnterpriseAuthRequest) (*EnterpriseAuthResult, error) {
if err := validateEnterpriseAuthRequest(req); err != nil {
return nil, err
}
accessToken, err := c.ensureAccessToken()
if err != nil {
return nil, err
}
clientCorpID := strings.TrimSpace(req.ClientCorpID)
if clientCorpID == "" {
clientCorpID = strings.TrimSpace(req.UnifiedSocialCode)
}
clientUserID := strings.TrimSpace(req.ClientUserID)
if clientUserID == "" {
clientUserID = strings.TrimSpace(req.TransactorID)
}
redirectURL := ""
if c.config.Auth != nil {
redirectURL = c.config.Auth.RedirectURL
}
apiReq := &getCorpAuthURLReq{
ClientCorpID: clientCorpID,
ClientUserID: clientUserID,
AccountName: strings.TrimSpace(req.TransactorMobile),
CorpIdentInfo: &corpIdentInfo{
CorpName: strings.TrimSpace(req.CompanyName),
// 按官方文档:不传默认为企业;置空让用户在页面选择组织类型
// CorpIdentType: "",
CorpIdentNo: strings.TrimSpace(req.UnifiedSocialCode),
LegalRepName: strings.TrimSpace(req.LegalPersonName),
CorpIdentMethod: []string{CorpIdentMethodLegalRep},
},
// 文档合法值仅 corpName/corpIdentType/corpIdentNo不传表示都可修改
// CorpNonEditableInfo: ,
OprIdentInfo: &oprIdentInfo{
UserName: strings.TrimSpace(req.TransactorName),
UserIdentType: UserIdentTypeIDCard,
UserIdentNo: strings.TrimSpace(req.TransactorID),
Mobile: strings.TrimSpace(req.TransactorMobile),
OprIdentMethod: []string{OprIdentMethodMobile},
},
OprNonEditableInfo: nil,
AuthScopes: append([]string{}, defaultAuthScopes...),
RedirectURL: encodeRedirectURL(redirectURL),
}
res, err := c.http.PostBiz(pathGetCorpAuthURL, accessToken, apiReq)
if err != nil {
return nil, err
}
if res.Code != successCode {
return nil, fmt.Errorf("获取法大大企业认证链接失败: code=%s msg=%s requestId=%s", res.Code, res.Msg, res.RequestID)
}
var data getCorpAuthURLData
if err := decodeData(res.Data, &data); err != nil {
return nil, fmt.Errorf("解析企业认证链接响应失败: %w", err)
}
if data.AuthURL == "" {
return nil, fmt.Errorf("获取法大大企业认证链接失败: authUrl 为空 requestId=%s", res.RequestID)
}
return &EnterpriseAuthResult{
AuthFlowID: clientCorpID,
AuthURL: data.AuthURL,
AuthShortURL: data.AuthURL,
}, nil
}
// QueryOrgVerified 查询企业是否已在法大大完成实名POST /corp/get-identified-status
func (c *Client) QueryOrgVerified(req *QueryOrgIdentityRequest) (bool, error) {
result, err := c.QueryOrgIdentity(req)
if err != nil {
return false, err
}
return result.Identified, nil
}
// QueryOrgIdentity 查询企业实名认证状态详情
func (c *Client) QueryOrgIdentity(req *QueryOrgIdentityRequest) (*QueryOrgIdentityResult, error) {
if req == nil {
return nil, fmt.Errorf("查询请求不能为空")
}
corpName := strings.TrimSpace(req.CorpName)
corpIdentNo := strings.TrimSpace(req.CorpIdentNo)
if corpName == "" && corpIdentNo == "" {
return nil, fmt.Errorf("企业名称与统一社会信用代码不能同时为空")
}
accessToken, err := c.ensureAccessToken()
if err != nil {
return nil, err
}
res, err := c.http.PostBiz(pathGetCorpIdentifiedStatus, accessToken, &getIdentifiedStatusReq{
CorpName: corpName,
CorpIdentNo: corpIdentNo,
})
if err != nil {
return nil, err
}
if res.Code != successCode {
return nil, fmt.Errorf("查询法大大企业实名状态失败: code=%s msg=%s requestId=%s", res.Code, res.Msg, res.RequestID)
}
var data getIdentifiedStatusData
if err := decodeData(res.Data, &data); err != nil {
return nil, fmt.Errorf("解析企业实名状态失败: %w", err)
}
return &QueryOrgIdentityResult{
Identified: data.IdentStatus,
CorpName: corpName,
CorpIdentNo: corpIdentNo,
}, nil
}
func validateEnterpriseAuthRequest(req *EnterpriseAuthRequest) error {
if req == nil {
return fmt.Errorf("认证请求不能为空")
}
if strings.TrimSpace(req.CompanyName) == "" {
return fmt.Errorf("企业名称不能为空")
}
if strings.TrimSpace(req.UnifiedSocialCode) == "" {
return fmt.Errorf("统一社会信用代码不能为空")
}
if strings.TrimSpace(req.LegalPersonName) == "" {
return fmt.Errorf("法人姓名不能为空")
}
if strings.TrimSpace(req.TransactorName) == "" {
return fmt.Errorf("经办人姓名不能为空")
}
if strings.TrimSpace(req.TransactorMobile) == "" {
return fmt.Errorf("经办人手机号不能为空")
}
if strings.TrimSpace(req.TransactorID) == "" {
return fmt.Errorf("经办人身份证号不能为空")
}
return nil
}
// encodeRedirectURL 按官方文档对 redirectUrl 做 URL encode已编码则原样返回
func encodeRedirectURL(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" {
return ""
}
if strings.Contains(raw, "%") {
if decoded, err := url.QueryUnescape(raw); err == nil && decoded != raw {
return raw
}
}
return url.QueryEscape(raw)
}