Skip to content
Bitzsoft.Integrationsbitzsoft.integrations

Concept

LegalDatabase 法律数据库

法律数据库域完整手册——功能标志枚举、适配器模式、SsoRedirectLegalDatabaseProvider 委托共享 SSO 域、12 家厂商能力矩阵与 Search/AccessUrl 决策。

Last updated

LegalDatabase 域覆盖 12 家法律数据库供应商。这是整个集成库里能力差异最大的域:8 家厂商只有 SSO 跳转入口,根本没有公开检索 API;4 家厂商提供 API 检索。抽象层用功能标志枚举声明能力差异,并通过内置适配器 SsoRedirectLegalDatabaseProvider 把 SSO 跳转委托给共享的 SsoRedirect 域。

本页是完整手册:从能力标志到适配器、从 SSO-only 厂商到 API 厂商、从 Search/AccessUrl 决策到厂商能力矩阵。

为什么需要适配器模式

标准三层模式假设所有厂商实现同一套完整接口。法律数据库的现实是:

  • 威科先行、法信、聚法案例、把手案例、见微、律商联讯、秘塔、无讼这 8 家只有 SSO 跳转入口,没有公开检索 API;
  • 元典、得理法搜、合享专利库这 3 家提供完整 API 检索
  • 北大法宝的能力是动态的——配了 ApiToken 才支持检索,否则只有跳转。

强行让 SSO 厂商实现 SearchAsync 会产生一堆空实现,调用方也无法判断哪些方法真的可用。适配器模式把”能力声明”和”能力实现”分离:

  • 厂商通过 Capabilities 属性声明自己支持哪些操作(功能标志);
  • 调用方在使用前用 HasFlag 检查标志位;
  • 不支持的操作直接抛 NotSupportedException,而不是返回空结果假装成功。

功能标志枚举

[Flags] 枚举,用位运算组合:

[Flags]
public enum LegalDatabaseCapabilities
{
None = 0,
AccessUrl = 1, // SSO 跳转:生成带认证参数的访问链接
Search = 2, // API 检索:关键词搜索法律文献
DocumentDetail = 4, // API 文档详情:获取单篇文档全文
All = AccessUrl | Search | DocumentDetail,
}

AccessUrl 是所有 12 家厂商都支持的基础能力;SearchDocumentDetail 只有 API 厂商才支持。

统一接口

public interface ILegalDatabaseProvider
{
string ProviderName { get; }
LegalDatabaseCapabilities Capabilities { get; } // 功能标志,调用方据此判断可用性
// AccessUrl 能力——所有厂商都支持
Task<LegalDatabaseAccessUrl> GenerateAccessUrlAsync(
string userId, string? redirectUrl = null, CancellationToken ct = default);
// Search 能力——仅 API 厂商支持
Task<LegalSearchResult> SearchAsync(
string keyword, LegalSearchType searchType = LegalSearchType.All,
int pageIndex = 1, int pageSize = 20, CancellationToken ct = default);
// DocumentDetail 能力——仅 API 厂商支持
Task<LegalDocument> GetDocumentAsync(string documentId, CancellationToken ct = default);
}

注意:和走 Result<T> 的电子签域不同,LegalDatabase 的接口直接返回模型对象LegalDatabaseAccessUrl / LegalSearchResult / LegalDocument)。失败时抛 LegalDatabaseException,把供应商错误码和消息封装在内。

SsoRedirectLegalDatabaseProvider 适配器

对只支持 SSO 跳转的厂商,抽象包内置了 SsoRedirectLegalDatabaseProvider。它实现 ILegalDatabaseProvider,把 GenerateAccessUrlAsync 委托给共享层的 SsoRedirectProvider,其余两个方法直接抛异常:

public class SsoRedirectLegalDatabaseProvider : ILegalDatabaseProvider, IDisposable
{
private readonly SsoRedirectProvider _inner;
public LegalDatabaseCapabilities Capabilities => LegalDatabaseCapabilities.AccessUrl;
public async Task<LegalDatabaseAccessUrl> GenerateAccessUrlAsync(
string userId, string? redirectUrl = null, CancellationToken ct = default)
{
var result = await _inner.GenerateAccessUrlAsync(userId, redirectUrl, ct);
return new LegalDatabaseAccessUrl { Url = result.Url, ExpiresAt = result.ExpiresAt };
}
public Task<LegalSearchResult> SearchAsync(...) =>
throw new NotSupportedException($"供应商 [{_inner.ProviderName}] 不支持 API 检索,仅支持 SSO 跳转访问");
public Task<LegalDocument> GetDocumentAsync(...) =>
throw new NotSupportedException($"供应商 [{_inner.ProviderName}] 不支持获取文档详情,仅支持 SSO 跳转访问");
}

这个适配器委托给共享的 SsoRedirect 域,而不是重新实现跳转逻辑。SsoRedirectProvider 支持 UrlTemplate 模式(拼接 URL)和 API 重定向模式(捕获 3xx Location),适配器的构造函数按需注入对应的 HttpClient

多数 SSO 厂商直接继承这个适配器,零代码即可接入。

12 家厂商能力矩阵

厂商中文Provider IDAccessUrlSearchDocumentDetail接入方式
WkInfo威科先行WkInfoSsoRedirect 配置注册
Faxin法信Faxin继承适配器
Jufaanli聚法案例Jufaanli继承适配器
Wusong无讼WusongSsoRedirect 配置注册
Metalaw秘塔Metalaw继承适配器
Lawsdata把手案例Lawsdata继承适配器
Jianwei见微Jianwei继承适配器
LexisNexis律商联讯LexisNexis继承适配器
Pkulaw北大法宝Pkulaw动态动态自有实现
Yuandian元典Yuandian自有实现
Delilegal得理法搜Delilegal自有实现
Incopat合享专利库Incopat自有实现

8 家纯 SSO 厂商(WkInfo / Faxin / Jufaanli / Wusong / Metalaw / Lawsdata / Jianwei / LexisNexis)只支持 AccessUrl,通过继承适配器或配置注册接入。

北大法宝的能力是动态的:配置了 ApiToken 时额外支持 SearchDocumentDetail,否则只有 AccessUrl。它的 Capabilities 属性在运行时读取配置决定。

3 家 API 厂商(Yuandian / Delilegal / Incopat)完整实现三个方法。

SSO 厂商(8 家)API 厂商(4 家)

Yuandian 元典

ILegalDatabaseProvider
自有实现

Delilegal 得理

Incopat 合享

Pkulaw 北大法宝
动态能力

WkInfo 威科

SsoRedirectLegalDatabaseProvider
适配器

Faxin 法信

Jufaanli 聚法

... 共 8 家

SsoRedirect 共享域

LegalSearchType 检索类型

SearchAsyncsearchType 参数限定检索范围:

名称说明
0All全部类型(默认)
1Law法律法规
2Case司法案例
3Patent专利(合享专利库专长)
4Journal法学期刊

不同 API 厂商对检索类型的支持粒度不同,部分类型可能并入 All 返回。

错误处理

LegalDatabaseException 继承 IntegrationExceptiondomain 固定为 "LegalDatabase"

public class LegalDatabaseException : IntegrationException
{
public string ProviderName => Provider ?? string.Empty;
public new string? ErrorCode => base.ErrorCode;
public new string? ProviderMessage => base.ProviderMessage;
public LegalDatabaseException(string providerName, string? errorCode, string? providerMessage)
: base(domain: "LegalDatabase",
message: $"[{providerName}] {errorCode}: {providerMessage}", ...) { }
}

抽象层还定义了 LegalDatabaseResult<T>(含 IsSuccess / Data / ErrorCode / ErrorMessageSuccess / Fail 工厂),但接口方法直接返回模型对象而非 Result——这是为未来 Result 化预留的类型,当前失败统一走异常路径。

Search vs AccessUrl:如何决策

场景用什么谁可用
用户点击后直接跳到厂商平台查阅GenerateAccessUrlAsync全部 12 家
在应用内嵌入检索框,返回结构化结果列表SearchAsync仅 4 家 API 厂商
点击检索结果查看单篇文档全文GetDocumentAsync仅 4 家 API 厂商
多厂商统一检索入口HasFlag(Search) 筛选可用厂商API 厂商子集

注册

单厂商

// ① 威科先行(纯 SSO,UrlTemplate 模式)
builder.Services.AddBitzsoftWkInfoLegalDatabase(builder.Configuration.GetSection("LegalDatabase:WkInfo"));
// ② 元典(API 检索,自有实现)
builder.Services.AddBitzsoftYuandianLegalDatabase(builder.Configuration.GetSection("LegalDatabase:Yuandian"));
// ③ 通用 SSO 跳转注册(任意 SsoRedirect 模式厂商,按配置注册)
builder.Services.AddBitzsoftSsoRedirectLegalDatabase(options =>
{
options.ProviderName = "威科先行";
options.SsoUrlTemplate = "https://www.wkinfo.com.cn/sso?uid={userId}&token={token}&t={timestamp}";
options.Token = "your-sso-token";
});

全量聚合

// 注意:聚合方法名是 AddBitzsoftLegalDatabase,不带 All 后缀
builder.Services.AddBitzsoftLegalDatabase(builder.Configuration, "LegalDatabase");

按配置节存在性自动注册:

{
"LegalDatabase": {
"WkInfo": { "ProviderName": "威科先行", "SsoUrlTemplate": "...", "Token": "..." },
"Yuandian": { "ApiBaseUrl": "...", "ApiKey": "..." },
"Pkulaw": { "BaseUrl": "...", "ApiToken": "..." }
}
}

消费

AccessUrl(所有厂商)

public class LegalAccessService(ILegalDatabaseProvider db)
{
public async Task<string> GetAccessUrlAsync(string userId)
{
var url = await db.GenerateAccessUrlAsync(userId);
return url.Url; // 带认证参数,直接返回给前端跳转
}
}

Search(仅 API 厂商)

public class LegalSearchService(ILegalDatabaseProvider db)
{
public async Task<IReadOnlyList<LegalDocument>> SearchAsync(string keyword)
{
// ① 检查能力标志,避免 NotSupportedException
if (!db.Capabilities.HasFlag(LegalDatabaseCapabilities.Search))
throw new NotSupportedException($"{db.ProviderName} 不支持 API 检索");
var result = await db.SearchAsync(keyword, LegalSearchType.All, pageIndex: 1, pageSize: 20);
return result.Items;
}
}

多厂商路由

public class LegalRouter(IIntegrationProviderResolver<ILegalDatabaseProvider> providers)
{
public async Task<LegalSearchResult> SearchAsync(string source, string keyword)
{
var db = providers.GetRequired(source); // "Yuandian" / "Delilegal" / "Pkulaw" ...
if (!db.Capabilities.HasFlag(LegalDatabaseCapabilities.Search))
throw new NotSupportedException($"{source} 不支持检索");
return await db.SearchAsync(keyword);
}
}

相关

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%