idata-client
v0.1.0
Published
数桥轻量连接器,帮助用户管理身份凭证、区域节点、业务节点,完成身份集成。
Readme
IData 统一身份登录 SDK
统一身份登录 SDK - 基于自定义协议调用桌面应用程序进行身份认证、身份注册、合约签署等功能
功能特性
- 🔐 统一身份认证
- 📝 数字合约签署
- 🏢 身份注册与管理
- 📋 身份凭证导入
- 🖥️ 桌面应用程序集成
- 📱 自定义协议支持
- ⏱️ 智能轮询机制
- 🔄 自动重试机制
- 💪 TypeScript 支持
- 🌐 多环境支持(浏览器、Electron)
安装
npm install idata-client或者使用 yarn:
yarn add idata-client快速开始
1. 统一身份登录
import { createIDataLogin } from 'idata-client';
// 区域/行业功能节点、业务节点ID
const nodeId = '212340000MB1M26392A340195BZZPGQX';
const IDataLogin = createIDataLogin({
options: {
nodeId, // 区域/行业功能节点、业务节点ID
},
callbacks: {
onLoading: (loading) => {
console.log('登录状态:', loading);
},
onSuccess: (token) => {
console.log('登录成功,Token:', token);
// 处理登录成功逻辑
if (token) {
// emit("login", token);
}
},
onError: (error) => {
console.error('登录失败:', error);
},
onMessage: (message, type) => {
console.log(`消息[${type}]:`, message);
},
},
});
// 点击登录按钮,开始登录
const handleLogin = () => {
IDataLogin.login();
};2. 签署合约
import { createIDataSignContract } from 'idata-client';
const IDataSignContract = createIDataSignContract({
options: {
contractData: '{"contractId":"12345","title":"采购合同","content":"..."}', // 合约数据
cn: 'example-company', // 主体标识
type: 1, // 1-区域,2-业务
},
callbacks: {
onLoading: (loading) => {
console.log('签署状态:', loading);
},
onSuccess: (signature) => {
console.log('签署成功,签名:', signature);
// 处理签署成功逻辑,将签名发送到后端
// api.submitContractSignature(signature);
},
onError: (error) => {
console.error('签署失败:', error);
},
onMessage: (message, type) => {
console.log(`消息[${type}]:`, message);
},
},
});
// 点击签署按钮,开始签署合约
const handleSignContract = () => {
IDataSignContract.signContract();
};3. 身份注册
import { createIDataRegister } from 'idata-client';
const IDataRegister = createIDataRegister({
callbacks: {
onLoading: (loading) => {
console.log('注册状态:', loading);
},
onSuccess: (certData) => {
console.log('注册成功,证书数据:', certData);
// 处理注册成功逻辑 certData的值是一个JSON字符串:"{\"csrJson\":\"-----BEGIN "}"
try {
const { csrJson } = JSON.parse(certData);
// emit("register", csrJson);
} catch (error) {
console.error('解析证书数据失败:', error);
}
},
onError: (error) => {
console.error('注册失败:', error);
},
onMessage: (message, type) => {
console.log(`消息[${type}]:`, message);
},
},
});
const handleRegister = () => {
// 凭证类型:1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证
const certType = '1';
// 企业名称
const orgName = '数据空间研究院';
// 国家代码
const countryCode = 'CN';
// 所属主体的标识(可选,连接器身份和业务节点身份必选)
// const ou = '研发部';
const subject = [
{ name: 'O', value: orgName }, // 企业名称(Organization)
{ name: 'C', value: countryCode }, // 国家代码(Country)
// { name: 'OU', value: ou }, // 所属主体的标识(Organizational Unit)
];
IDataRegister.registerIdentity({
certType, // 凭证类型,必选
subject: JSON.stringify(subject), // 主体信息,必选
// didMethod: 'ethr', // DID方法,可选
});
};
### 参数说明
| 参数 | 类型 | 必选/可选 | 说明 |
|------|------|----------|------|
| `certType` | string | 必选 | 凭证类型。可选值:"1"(主体身份)、"2"(连接器身份)、"3"(业务节点身份) |
| `subject` | string \| object \| array | 必选 | 主体信息,支持三种格式:<br>1. JSON 字符串格式:`'{"O":"企业名称","C":"CN"}'`<br>2. 对象格式:`{O:"企业名称",C:"CN"}`<br>3. 数组格式:`[{name:"O",value:"企业名称"},{name:"C",value:"CN"}]` |
| `didMethod` | string | 可选 | DID方法 |
### subject 字段说明
| 字段 | 类型 | 必选/可选 | 说明 |
|------|------|----------|------|
| `O` | string | 必选 | 企业名称(Organization) |
| `OU` | string | 可选 | 所属主体的标识(Organizational Unit),主体身份可不填,业务节点、接入连接器身份必选 |
| `C` | string | 必选 | 国家代码(Country) |
### 回调函数说明
| 回调函数 | 类型 | 说明 |
|----------|------|------|
| `onLoading` | `(loading: boolean) => void` | 加载状态变化回调 |
| `onSuccess` | `(certData: string) => void` | 注册成功回调,参数 certData 是证书数据(JSON 字符串) |
| `onError` | `(error: Error \| any) => void` | 注册失败回调,参数 error 为错误信息 |
| `onMessage` | `(message: string, type?: string) => void` | 消息回调,参数 message 为消息内容,type 为消息类型 |4. 身份凭证导入
import { createIDataImportVc } from 'idata-client';
const IDataImportVc = createIDataImportVc({
callbacks: {
onLoading: (loading) => {
console.log('导入状态:', loading);
},
onSuccess: (result) => {
console.log('导入成功:', result);
},
onError: (error) => {
console.error('导入失败:', error);
},
onMessage: (message, type) => {
console.log(`消息[${type}]:`, message);
},
},
});
const handleImport = () => {
// 证书内容
const crt = `-----BEGIN CERTIFICATE-----
MIIDNDCCAhygAwIBAgIUborye/q2vMhxsjmmqZpx+eEXxykwDQYJKoZIhvcNAQEF
BQAwJTEKMAgGA1UEAwwBYTEKMAgGA1UECgwBYTELMAkGA1UEBhMCQ04wHhcNMjUw
NzEzMDY1MzAwWhcNMjkwNzA1MDY1MDAwWjBkMQswCQYDVQQGEwJDTjEPMA0GA1UE
CAwG5YyX5LqsMQ8wDQYDVQQHDAbljJfkuqwxGzAZBgNVBAoMEuenkeaKgOaciemZ
kOWFrOWPuDEWMBQGA1UEAwwNd3d3LmJhaWR1LmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKtsbM7tL/gJmpwBH2WT1pmat6qWAWuWlLdiW4WiX7MZ
O8VHvMgmcnhFmJ5BRZ0VUZbHF2yWw/WoOCSMktFhqJ2NhjAYRxxTvd3sGbDncPEn
0/2VSfjtjuTp4JrQe+mR6Ki1KNTuNQTBLOb1lCImPhUt1PmMqr4MpPuJlqWCs86+
doTgtWZftP2SxeinkD+HAuQ4ohH47sINTWZgkjFI9Ctu05dGR3T/UdraELgs0u41
c/ANmrQX0KLEhDOSIYgRnnApFT21Jp+I0pfuVVretLyPinK351HfvSpiSRi9oHSp
CjK3Q70cNG7iyieqYmksWBo0dge9uvi7ufB+19viJI0CAwEAAaMdMBswCwYDVR0R
BAQwAoIAMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEFBQADggEBAJkHSavndKwY
g7J0BFvGYxQQjNmWtN19zgehnNKQBRRSgVve710AjsiIhsnfF0JWY+bOMmTg3055
wp/8U9vMEsKYj7BOci8jMvI+7mcid6XgOPOgCV6t0mXQ5o7bWxVGNerVtNuPmcuY
5JCcnq9kGlzPXNsH7zc3T9HNtgn2Mjw8+3mLZElIApEz3XV4dtw1afRzuoM+bH04
Arz7S/A6RwVSa3twaihggmhLIGzxJyq5k60aeK35If5KNouPn5E12uUHAgjDs67+
asd9tWOH8zKR161kQ0xybhZfJPiUAJ3NWWqJFV+V4V7Z4KfzZ9oCLs+ObHCqCGky
dZOehfiSF2A=
-----END CERTIFICATE-----`;
const certType = '1'; // 凭证类型 1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证
// 区域功能节点api地址
const apiUrl = 'https://idata.com/api';
const certData = {
crt, // 证书内容
certType, // 凭证类型
apiUrl, // 区域功能节点api地址
};
IDataImportVc.importCert(certData);
};Vue.js 集成示例
合约签署组件
<template>
<div>
<div class="contract-section">
<h3>合约签署</h3>
<div class="contract-info">
<p><strong>合约标题:</strong>{{ contractTitle }}</p>
<p><strong>合约ID:</strong>{{ contractId }}</p>
<p><strong>合约摘要:</strong>{{ contractSummary }}</p>
</div>
<button
@click="handleSignContract"
:disabled="loading"
class="sign-button"
>
{{ loading ? '签署中...' : '签署合约' }}
</button>
<div
v-if="message"
class="message"
>
{{ message }}
</div>
<div
v-if="signature"
class="signature-result"
>
<h4>签署成功</h4>
<p>签名结果:</p>
<pre>{{ signature }}</pre>
</div>
</div>
</div>
</template>
<script>
import { createIDataSignContract } from 'idata-client';
export default {
data() {
return {
loading: false,
message: '',
signature: '',
contractTitle: '采购合同',
contractId: 'CONTRACT-2024-001',
contractSummary: '此合同规定了采购方与供应商之间的权利义务关系...',
IDataSignContract: null,
};
},
created() {
this.IDataSignContract = createIDataSignContract({
options: {
contractData: JSON.stringify({
contractId: this.contractId,
title: this.contractTitle,
content: '完整的合约内容...',
parties: [
{ name: '采购方', role: 'buyer' },
{ name: '供应商', role: 'supplier' },
],
effectiveDate: new Date().toISOString(),
expirationDate: new Date(
Date.now() + 365 * 24 * 60 * 60 * 1000,
).toISOString(),
}),
cn: 'example-company', // 主体标识
type: 1, // 1-区域,2-业务
},
callbacks: {
onLoading: (loading) => {
this.loading = loading;
},
onSuccess: (signature) => {
this.message = '合约签署成功!';
this.signature = signature;
// 将签名发送到后端
this.submitSignatureToBackend(signature);
},
onError: (error) => {
this.message = `签署失败: ${error.message}`;
},
onMessage: (message, type) => {
this.message = message;
if (type === 'error') {
console.error('签署错误:', message);
}
},
},
});
},
methods: {
handleSignContract() {
this.signature = ''; // 清除之前的签名
this.IDataSignContract.signContract();
},
async submitSignatureToBackend(signature) {
try {
// 调用后端API提交签名
const response = await fetch('/api/contracts/sign', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contractId: this.contractId,
signature: signature,
timestamp: new Date().toISOString(),
}),
});
if (response.ok) {
console.log('签名已成功提交到后端');
} else {
console.error('提交签名到后端失败');
}
} catch (error) {
console.error('提交签名时出错:', error);
}
},
},
beforeDestroy() {
if (this.IDataSignContract) {
this.IDataSignContract.destroy();
}
},
};
</script>登录组件
<template>
<div>
<button
@click="handleLogin"
:disabled="loading"
>
{{ loading ? '登录中...' : '统一身份登录' }}
</button>
<div v-if="message">{{ message }}</div>
</div>
</template>
<script>
import { createIDataLogin } from 'idata-client';
export default {
data() {
return {
loading: false,
message: '',
IDataLogin: null,
};
},
created() {
// 区域/行业功能节点、业务节点ID
const nodeId = '212340000MB1M26392A340195BZZPGQX';
this.IDataLogin = createIDataLogin({
options: {
nodeId, // 区域/行业功能节点、业务节点ID
},
callbacks: {
onLoading: (loading) => {
this.loading = loading;
},
onSuccess: (token) => {
this.message = '登录成功!';
localStorage.setItem('authToken', token);
this.$router.push('/dashboard');
},
onError: (error) => {
this.message = `登录失败: ${error.message}`;
},
onMessage: (message, type) => {
this.message = message;
},
},
});
},
methods: {
handleLogin() {
this.IDataLogin.login();
},
},
beforeDestroy() {
if (this.IDataLogin) {
this.IDataLogin.destroy();
}
},
};
</script>注册组件
<template>
<div>
<button
@click="handleRegister"
:disabled="loading"
>
{{ loading ? '注册中...' : '注册数字身份' }}
</button>
<div v-if="message">{{ message }}</div>
</div>
</template>
<script>
import { createIDataRegister } from 'idata-client';
export default {
data() {
return {
loading: false,
message: '',
IDataRegister: null,
};
},
created() {
this.IDataRegister = createIDataRegister({
callbacks: {
onLoading: (loading) => {
this.loading = loading;
},
onSuccess: (certData) => {
this.message = '注册成功!';
console.log('证书数据:', certData);
// 处理注册成功逻辑 - 解析证书数据
try {
const { csrJson } = JSON.parse(certData);
console.log('解析后的CSR:', csrJson);
// 可以将CSR数据保存到本地存储或发送到后端
localStorage.setItem('csrData', csrJson);
} catch (error) {
console.error('解析证书数据失败:', error);
}
},
onError: (error) => {
this.message = `注册失败: ${error.message}`;
},
onMessage: (message, type) => {
this.message = message;
},
},
});
},
methods: {
handleRegister() {
// 凭证类型:1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证
const certType = '1';
// 企业名称
const orgName = '数据空间研究院';
// 国家代码
const countryCode = 'CN';
// 所属主体的标识(可选,连接器身份和业务节点身份必选)
// const ou = '研发部';
const subject = [
{ name: 'O', value: orgName }, // 企业名称(Organization)
{ name: 'C', value: countryCode }, // 国家代码(Country)
// { name: 'OU', value: ou }, // 所属主体的标识(Organizational Unit)
];
this.IDataRegister.registerIdentity({
certType, // 凭证类型,必选
subject: JSON.stringify(subject), // 主体信息,必选
// didMethod: 'ethr', // DID方法,可选
});
},
},
beforeDestroy() {
if (this.IDataRegister) {
this.IDataRegister.destroy();
}
},
};
</script>React 集成示例
合约签署组件
import React, { useState, useEffect, useRef } from 'react';
import { createIDataSignContract } from 'idata-client';
function ContractSignComponent() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState('');
const [signature, setSignature] = useState('');
const [contractData, setContractData] = useState({
title: '采购合同',
id: 'CONTRACT-2024-001',
summary: '此合同规定了采购方与供应商之间的权利义务关系...',
});
const IDataSignContractRef = useRef(null);
useEffect(() => {
IDataSignContractRef.current = createIDataSignContract({
options: {
contractData: JSON.stringify({
contractId: contractData.id,
title: contractData.title,
content: '完整的合约内容...',
parties: [
{ name: '采购方', role: 'buyer' },
{ name: '供应商', role: 'supplier' },
],
effectiveDate: new Date().toISOString(),
expirationDate: new Date(
Date.now() + 365 * 24 * 60 * 60 * 1000,
).toISOString(),
}),
cn: 'example-company',
type: 1,
},
callbacks: {
onLoading: setLoading,
onSuccess: (signature) => {
setMessage('合约签署成功!');
setSignature(signature);
// 将签名发送到后端
submitSignatureToBackend(signature);
},
onError: (error) => {
setMessage(`签署失败: ${error.message}`);
},
onMessage: (message) => {
setMessage(message);
},
},
});
return () => {
if (IDataSignContractRef.current) {
IDataSignContractRef.current.destroy();
}
};
}, [contractData]);
const handleSignContract = () => {
setSignature(''); // 清除之前的签名
IDataSignContractRef.current?.signContract();
};
const submitSignatureToBackend = async (signature) => {
try {
const response = await fetch('/api/contracts/sign', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contractId: contractData.id,
signature: signature,
timestamp: new Date().toISOString(),
}),
});
if (response.ok) {
console.log('签名已成功提交到后端');
} else {
console.error('提交签名到后端失败');
}
} catch (error) {
console.error('提交签名时出错:', error);
}
};
return (
<div style={{ maxWidth: '600px', margin: '20px 0' }}>
<div
style={{
padding: '20px',
border: '1px solid #e0e0e0',
borderRadius: '8px',
backgroundColor: '#f9f9f9',
}}
>
<h3>合约签署</h3>
<div
style={{
marginBottom: '20px',
padding: '15px',
backgroundColor: 'white',
borderRadius: '4px',
borderLeft: '4px solid #007bff',
}}
>
<p>
<strong>合约标题:</strong>
{contractData.title}
</p>
<p>
<strong>合约ID:</strong>
{contractData.id}
</p>
<p>
<strong>合约摘要:</strong>
{contractData.summary}
</p>
</div>
<button
onClick={handleSignContract}
disabled={loading}
style={{
padding: '10px 20px',
backgroundColor: loading ? '#ccc' : '#28a745',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: loading ? 'not-allowed' : 'pointer',
fontSize: '16px',
transition: 'background-color 0.3s',
}}
>
{loading ? '签署中...' : '签署合约'}
</button>
{message && (
<div
style={{
marginTop: '15px',
padding: '10px',
borderRadius: '4px',
border: '1px solid #dee2e6',
}}
>
{message}
</div>
)}
{signature && (
<div
style={{
marginTop: '20px',
padding: '15px',
backgroundColor: '#d4edda',
border: '1px solid #c3e6cb',
borderRadius: '4px',
}}
>
<h4>签署成功</h4>
<p>签名结果:</p>
<pre
style={{
backgroundColor: '#f8f9fa',
padding: '10px',
borderRadius: '4px',
overflowX: 'auto',
fontSize: '12px',
}}
>
{signature}
</pre>
</div>
)}
</div>
</div>
);
}
export default ContractSignComponent;登录组件
import React, { useState, useEffect, useRef } from 'react';
import { createIDataLogin } from 'idata-client';
function LoginComponent() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState('');
const IDataLoginRef = useRef(null);
useEffect(() => {
// 区域/行业功能节点、业务节点ID
const nodeId = '212340000MB1M26392A340195BZZPGQX';
IDataLoginRef.current = createIDataLogin({
options: {
nodeId, // 区域/行业功能节点、业务节点ID
},
callbacks: {
onLoading: setLoading,
onSuccess: (token) => {
setMessage('登录成功!');
localStorage.setItem('authToken', token);
// 跳转到主页或处理登录成功逻辑
},
onError: (error) => {
setMessage(`登录失败: ${error.message}`);
},
onMessage: (message) => {
setMessage(message);
},
},
});
return () => {
if (IDataLoginRef.current) {
IDataLoginRef.current.destroy();
}
};
}, []);
const handleLogin = () => {
IDataLoginRef.current?.login();
};
return (
<div>
<button
onClick={handleLogin}
disabled={loading}
>
{loading ? '登录中...' : '统一身份登录'}
</button>
{message && <div>{message}</div>}
</div>
);
}
export default LoginComponent;注册组件
import React, { useState, useEffect, useRef } from 'react';
import { createIDataRegister } from 'idata-client';
function RegisterComponent() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState('');
const IDataRegisterRef = useRef(null);
useEffect(() => {
IDataRegisterRef.current = createIDataRegister({
callbacks: {
onLoading: setLoading,
onSuccess: (certData) => {
setMessage('注册成功!');
console.log('证书数据:', certData);
// 处理注册成功逻辑 - 解析证书数据
try {
const { csrJson } = JSON.parse(certData);
console.log('解析后的CSR:', csrJson);
// 可以将CSR数据保存到本地存储或发送到后端
localStorage.setItem('csrData', csrJson);
} catch (error) {
console.error('解析证书数据失败:', error);
}
},
onError: (error) => {
setMessage(`注册失败: ${error.message || error}`);
},
onMessage: (message) => {
setMessage(message);
},
},
});
return () => {
if (IDataRegisterRef.current) {
IDataRegisterRef.current.destroy();
}
};
}, []);
const handleRegister = () => {
// 凭证类型:1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证
const certType = '1';
// 企业名称
const orgName = '数据空间研究院';
// 国家代码
const countryCode = 'CN';
// 所属主体的标识(可选,连接器身份和业务节点身份必选)
// const ou = '研发部';
const subject = [
{ name: 'O', value: orgName }, // 企业名称(Organization)
{ name: 'C', value: countryCode }, // 国家代码(Country)
// { name: 'OU', value: ou }, // 所属主体的标识(Organizational Unit)
];
IDataRegisterRef.current?.registerIdentity({
certType, // 凭证类型,必选
subject: JSON.stringify(subject), // 主体信息,必选
// didMethod: 'ethr', // DID方法,可选
});
};
return (
<div>
<button
onClick={handleRegister}
disabled={loading}
>
{loading ? '注册中...' : '注册数字身份'}
</button>
{message && <div>{message}</div>}
</div>
);
}
export default RegisterComponent;配置选项
IDataLoginOptions
| 参数 | 类型 | 默认值 | 说明 |
| ----------------- | -------- | ------------------------ | ------------------------------------- |
| pollingTimeout | number | 600000 | 轮询超时时间(毫秒),默认10分钟 |
| pollingInterval | number | 1000 | 轮询间隔(毫秒),默认1秒 |
| IDataServerUrl | string | http://localhost:4521 | API基础URL |
| certificate | string | '' | 证书 |
| requestTimeout | number | 60000 | HTTP请求超时时间(毫秒),默认60秒 |
| apiEndpoints | object | 见API端点配置 | API端点配置 |
| baseUrl | string | window.location.origin | 域名配置(用于桌面应用调用) |
| type | number | 1 | 类型参数 1-区域,2-业务 |
| clientType | string | 自动检测 | 客户端类型(browser/electron/server) |
| cn | string | '' | 主体标识 |
| contractData | string | '' | 合约数据(JSON字符串) |
| nodeId | string | '' | 区域节点标识(登录必需) |
API端点配置
| 参数 | 类型 | 默认值 | 说明 |
| --------------- | -------- | -------------------- | --------------------- |
| getAuthResult | string | /get/authResult | 登录-认证结果 |
| getToken | string | /get/token | 登录-获取token |
| getCert | string | /get/cert | 注册-获取证书 |
| importCert | string | /import/cert | 获取身份凭证-导入证书 |
| createCert | string | /create/cert | 创建证书 |
| updateCert | string | /import/updateCert | 更新证书 |
| getSign | string | /get/sign | 获取合约签署 |
IDataSignContractOptions
| 参数 | 类型 | 默认值 | 说明 |
| -------------- | -------- | ------ | ----------------------- |
| contractData | string | '' | 合约数据(JSON 字符串) |
| cn | string | '' | 主体标识 |
| type | number | 1 | 类型参数 1-区域,2-业务 |
IDataLoginCallbacks
| 参数 | 类型 | 说明 |
| ----------- | ------------------------------------------ | -------------------------------------------------------------------- |
| onLoading | (loading: boolean) => void | 加载状态变化回调 |
| onSuccess | (data: any) => void | 成功回调,返回相应数据 |
| onError | (error: IDataError) => void | 错误回调,返回错误对象 |
| onMessage | (message: string, type?: string) => void | 消息回调,type 可选值: 'info', 'error', 'warning', 'success', 'CORS' |
IDataError 接口
interface IDataError {
/** 错误消息 */
message: string;
/** 错误数据 */
data?: {
message?: string;
data?: any;
};
/** 原始错误对象 */
originalError?: Error;
/** HTTP状态码 */
status?: number;
/** 错误类型 */
type?: string;
/** 请求URL */
url?: string;
}TypeScript 类型定义
import {
createIDataLogin,
createIDataRegister,
createIDataImportVc,
createIDataSignContract,
IDataLoginConfig,
IDataLoginOptions,
IDataLoginCallbacks,
RegisterIdentityParams,
CertData,
ErrorCode,
IDataError,
type IDATA,
} from 'idata-client';身份凭证数据结构
const certData = {
crt: 'string', // 证书内容-----BEGIN CERTIFICATE-----\nXXX-----END CERTIFICATE-----(必填)
apiUrl: 'string', // 接口地址(必填)
certType: '1', // 凭证类型 1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证(可选)
};合约数据结构
const contractData = {
contractId: 'string', // 合约ID
title: 'string', // 合约标题
content: 'string', // 合约内容
parties: Array<{ // 合约参与方
name: 'string',
role: 'string'
}>,
effectiveDate: 'string', // 生效日期(ISO格式)
expirationDate: 'string', // 到期日期(ISO格式)
// 其他自定义字段...
};TypeScript 使用示例
类型导入
import {
createIDataLogin,
createIDataRegister,
createIDataImportVc,
createIDataSignContract,
IDataLoginConfig,
IDataLoginOptions,
IDataLoginCallbacks,
RegisterIdentityParams,
CertData,
ErrorCode,
IDataError,
IDATA,
} from 'idata-client';登录示例
import { createIDataLogin, ErrorCode } from 'idata-client';
const loginConfig: IDataLoginConfig = {
options: {
nodeId: 'example-node-id',
},
callbacks: {
onLoading: (loading: boolean) => {
console.log('登录状态:', loading);
},
onSuccess: (data: any) => {
console.log('登录成功:', data);
},
onError: (error: IDataError) => {
console.error('登录错误:', error);
if (error.message.includes(ErrorCode.LOGIN_MISSING_NODE_ID)) {
console.error('错误:缺少 nodeId 参数');
}
},
onMessage: (message: string, type: string) => {
console.log(`[${type}]`, message);
},
},
};
const IDataLogin = createIDataLogin(loginConfig);
IDataLogin.login();注册示例
import { createIDataRegister } from 'idata-client';
const registerConfig: IDataLoginConfig = {
callbacks: {
onSuccess: (data: any) => {
const certData = JSON.parse(data);
console.log('注册成功:', certData);
},
onError: (error: IDataError) => {
console.error('注册错误:', error);
},
},
};
const IDataRegister = createIDataRegister(registerConfig);
const registerParams: RegisterIdentityParams = {
certType: '1',
subject: JSON.stringify({
O: '企业名称',
C: 'CN',
OU: '所属主体的标识',
}),
};
IDataRegister.registerIdentity(registerParams);导入凭证示例
import { createIDataImportVc, CertData } from 'idata-client';
const importConfig: IDataLoginConfig = {
callbacks: {
onSuccess: (data: any) => {
console.log('导入成功:', data);
},
onError: (error: IDataError) => {
console.error('导入错误:', error);
},
},
};
const IDataImportVc = createIDataImportVc(importConfig);
const certData: CertData = {
crt: '-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----',
apiUrl: 'https://api.example.com',
certType: '1',
};
IDataImportVc.importCert(certData);签署合约示例
import { createIDataSignContract } from 'idata-client';
const signConfig: IDataLoginConfig = {
options: {
contractData: JSON.stringify({
contractId: 'CONTRACT-001',
title: '采购合同',
content: '...',
}),
cn: 'example-company',
type: 1,
},
callbacks: {
onSuccess: (signature: string) => {
console.log('签署成功:', signature);
},
onError: (error: IDataError) => {
console.error('签署错误:', error);
},
},
};
const IDataSignContract = createIDataSignContract(signConfig);
IDataSignContract.signContract();API 方法
登录相关
login()
开始统一身份登录流程。
await IDataLogin.login();合约签署相关
signContract()
开始合约签署流程。
await IDataSignContract.signContract();注册相关
registerIdentity(params)
注册身份(1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证)。
// 注册
await IDataRegister.registerIdentity({
certType: '1', // 凭证类型,必选。可选值:"1"(主体身份)、"2"(连接器身份)、"3"(业务节点身份)
subject: '{"O":"企业名称","C":"CN"}', // 主体信息,必选
});参数说明:
certType(必填): 凭证类型,可选值:"1"(主体身份)、"2"(连接器身份)、"3"(业务节点身份)subject(必填): 主体信息,支持三种格式:- JSON 字符串格式:
'{"O":"企业名称","C":"CN"}' - 对象格式:
{O:"企业名称",C:"CN"} - 数组格式:
[{name:"O",value:"企业名称"},{name:"C",value:"CN"}]支持的字段:O(企业名称,必选)、OU(所属主体的标识,可选)、C(国家代码,必选)
- JSON 字符串格式:
didMethod(可选): DID方法
凭证导入相关
importCert(certData)
导入身份凭证。
const certData = {
crt: '-----BEGIN CERTIFICATE-----\nXXX-----END CERTIFICATE-----', // 证书内容(必填)
apiUrl: 'http://example.com/api', // 接口地址(必填)
certType: '1', // 证书类型 1-主体身份 2-连接器身份 3-业务节点身份(可选)
};
await IDataImportVc.importCert(certData);工厂函数
createIDataLogin(config)
创建登录实例。
import { createIDataLogin } from 'idata-client';
const IDataLogin = createIDataLogin(config);createIDataSignContract(config)
创建合约签署实例。
import { createIDataSignContract } from 'idata-client';
const IDataSignContract = createIDataSignContract(config);createIDataRegister(config)
创建注册实例。
import { createIDataRegister } from 'idata-client';
const IDataRegister = createIDataRegister(config);createIDataImportVc(config)
创建凭证导入实例。
import { createIDataImportVc } from 'idata-client';
const IDataImportVc = createIDataImportVc(config);注意事项
- 桌面应用依赖:此 SDK 依赖于桌面应用程序,需要确保目标设备已安装相应的桌面客户端
- 自定义协议:自定义协议
IData://和idata://需要在桌面应用程序中正确注册 - 服务器配置:确保 IData 服务器正确配置并运行在指定端口(默认 4521)
- 资源清理:建议在组件销毁时调用
destroy()方法以释放资源 - 错误处理:建议实现完整的错误处理机制,包括网络错误、超时等情况
- 合约数据:合约数据需要正确格式化,建议使用 JSON 字符串格式
- 签署上下文:合约签署需要在用户明确知晓合约内容的情况下进行
错误处理
错误码列表
登录相关错误码 (JS10xx)
| 错误码 | 描述 | 解决方案 |
| -------- | --------------------- | ------------------------------------------ |
| JS1001 | 缺少必需参数 nodeId | 请确保在配置中提供正确的 nodeId 参数 |
| JS1002 | nodeId 参数值无效 | 请确保 nodeId 是有效的字符串格式 |
| JS1004 | 请求失败/身份认证失败 | 请检查网络连接、服务器状态或联系平台方处理 |
身份注册错误码 (JS30xx)
| 错误码 | 描述 | 解决方案 |
| -------- | ------------------------------------------------ | -------------------------------------------------------------------------- |
| JS3001 | 缺少必需参数 certType | 请提供 certType 参数,可选值:"1"、"2"、"3" |
| JS3002 | certType 参数值无效 | certType 必须是 "1"(主体身份)、"2"(连接器身份)或 "3"(业务节点身份) |
| JS3003 | 缺少必需参数 subject | 请提供有效的 subject 主体信息 |
| JS3004 | subject 参数格式无效 | subject 必须是有效的 JSON 字符串格式或数组格式 |
| JS3005 | subject 缺少必填字段 O(企业名称) | 请在 subject 中添加 O 字段,如 {"O":"企业名称"} |
| JS3006 | subject 缺少必填字段 C(国家代码) | 请在 subject 中添加 C 字段,如 {"C":"CN"} |
| JS3007 | subject 缺少必填字段 OU(连接器/业务节点必需) | 当 certType 为 "2" 或 "3" 时,必须在 subject 中添加 OU 字段 |
身份凭证导入错误码 (JS40xx)
| 错误码 | 描述 | 解决方案 |
| -------- | --------------------- | ------------------------------ |
| JS4001 | 缺少必需参数 crt | 请提供有效的证书内容(crt) |
| JS4002 | 缺少必需参数 apiUrl | 请提供有效的接口地址(apiUrl) |
| JS4003 | 请求失败 | 请检查网络连接和服务器状态 |
常见错误情况
- 网络连接失败
- 服务器响应错误
- 桌面应用程序未安装
- 自定义协议未注册
- 轮询超时
- 合约数据格式错误
- 用户拒绝签署
- 跨域请求被阻止
- 请求超时
错误处理建议
const IDataSignContract = createIDataSignContract({
callbacks: {
onError: (error) => {
console.error('合约签署错误:', error);
console.error('错误类型:', error.type);
console.error('错误URL:', error.url);
// 根据错误码进行处理
if (error.message.includes('JS1001')) {
// 缺少 nodeId 参数
alert('登录参数不完整,请联系管理员');
} else if (error.message.includes('JS3001')) {
// 缺少 certType 参数
alert('注册参数不完整,请选择凭证类型');
} else if (error.message.includes('JS4001')) {
// 缺少证书参数
alert('请提供有效的证书内容');
} else if (error.type === 'CORS') {
// 跨域错误
alert('跨域请求被阻止,请检查服务器CORS配置');
} else if (error.type === 'error' && error.message.includes('timeout')) {
// 超时错误
alert('操作超时,请检查网络连接后重试');
} else if (error.message.includes('refuse')) {
// 用户拒绝或客户端繁忙
alert('客户端正忙,请稍后再试');
} else {
// 其他错误
alert('操作失败:' + error.message);
}
},
onMessage: (message, type) => {
if (type === 'error') {
console.error('错误消息:', message);
} else if (type === 'CORS') {
console.warn('跨域警告:', message);
}
},
},
});完整错误处理示例
import { createIDataLogin } from 'idata-client';
const IDataLogin = createIDataLogin({
options: {
nodeId: 'example-node-id', // 必须提供
},
callbacks: {
onLoading: (loading) => {
console.log('加载状态:', loading);
},
onSuccess: (token) => {
console.log('登录成功:', token);
},
onError: (error) => {
// 检查错误消息中的错误码
if (error.message.includes('JS1001')) {
console.error('错误:缺少 nodeId 参数');
} else if (error.message.includes('JS1002')) {
console.error('错误:nodeId 无效');
} else if (error.type === 'CORS') {
console.error('跨域错误:', error.message);
} else if (error.type === 'error' && error.message.includes('timeout')) {
console.error('超时错误:', error.message);
} else {
console.error('未知错误:', error);
}
},
onMessage: (message, type) => {
console.log(`[${type}]`, message);
},
},
});浏览器兼容性
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- 支持现代浏览器的自定义协议处理
许可证
MIT License
贡献
欢迎提交 Issue 和 Pull Request 来改进这个项目。
