package fadada import ( "errors" "fmt" "regexp" "strings" ) // 法大大 FASC OpenAPI 错误码(以官方「错误码说明」文档 code 为准,勿依赖 msg 文案)。 // 文档:https://dev.fadada.com/api-doc/JOQQIJXLFL/H4F0HSKMHQ3HPIIM/5-1 const ( CodeSuccess = "100000" // 请求成功 // 公共 CodeUnknownException = "100001" // 不可预知异常 CodeAccessTokenInvalid = "100002" // 访问凭证失效 CodeSignInvalid = "100003" // 接口签名错误 CodeTooFrequent = "100004" // 请求频繁 CodeParamIllegal = "100011" // 请求参数非法 CodeParamEmpty = "100012" // 请求参数为空 CodeBusinessIDNotFound = "212007" // 业务场景标识不存在 // get-auth-url 返回「授权范围重复获取」时可用作兜底(非正式查授权接口) // 正式查授权请用 POST /corp/get 的 bindingStatus CodeAuthScopeDuplicate = "210002" // 授权范围重复获取 CodeAuthScopeDuplicateCorp = "210013" // 授权范围重复获取(无须重复获取授权申请链接) CodeCorpNotFound = "210032" // 企业用户不存在 ) // APIError 法大大业务错误(按 code 判断,不依赖 msg) type APIError struct { Op string // 调用场景说明 Code string Msg string RequestID string } func (e *APIError) Error() string { if e == nil { return "" } op := strings.TrimSpace(e.Op) if op == "" { op = "法大大接口调用失败" } return fmt.Sprintf("%s: code=%s msg=%s requestId=%s", op, e.Code, e.Msg, e.RequestID) } // NewAPIError 构造结构化业务错误 func NewAPIError(op, code, msg, requestID string) *APIError { return &APIError{ Op: strings.TrimSpace(op), Code: strings.TrimSpace(code), Msg: strings.TrimSpace(msg), RequestID: strings.TrimSpace(requestID), } } // IsAuthAlreadyGranted 是否为 get-auth-url「授权范围重复获取」错误码(210002/210013)。 // 注意:正式判断是否已授权应调用 POST /corp/get(bindingStatus=authorized); // 本函数仅作取链失败时的兜底。 func IsAuthAlreadyGranted(err error) bool { if err == nil { return false } var apiErr *APIError if errors.As(err, &apiErr) && apiErr != nil { return isAuthAlreadyGrantedCode(apiErr.Code) } return isAuthAlreadyGrantedCode(extractFadadaCode(err.Error())) } func isAuthAlreadyGrantedCode(code string) bool { switch strings.TrimSpace(code) { case CodeAuthScopeDuplicate, CodeAuthScopeDuplicateCorp: return true default: return false } } var fadadaCodeRe = regexp.MustCompile(`(?i)(?:^|[^\d])code\s*=\s*(\d{6})(?:[^\d]|$)`) func extractFadadaCode(msg string) string { m := fadadaCodeRe.FindStringSubmatch(msg) if len(m) < 2 { return "" } return m[1] }