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 家厂商都支持的基础能力;Search 和 DocumentDetail 只有 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威科先行WkInfo✓——SsoRedirect 配置注册
Faxin法信Faxin✓——继承适配器
Jufaanli聚法案例Jufaanli✓——继承适配器
Wusong无讼Wusong✓——SsoRedirect 配置注册
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 时额外支持 Search 和 DocumentDetail,否则只有 AccessUrl。它的 Capabilities 属性在运行时读取配置决定。

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

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

Yuandian 元典

ILegalDatabaseProvider
自有实现

Delilegal 得理

Incopat 合享

Pkulaw 北大法宝
动态能力

WkInfo 威科

SsoRedirectLegalDatabaseProvider
适配器

Faxin 法信

Jufaanli 聚法

... 共 8 家

SsoRedirect 共享域

LegalSearchType 检索类型

SearchAsync 的 searchType 参数限定检索范围:

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

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

错误处理

LegalDatabaseException 继承 IntegrationException,domain 固定为 "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 / ErrorMessage 与 Success / 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%