dnp-client
Version:
数据基础设施轻量连接器,帮助用户管理身份凭证、区域节点、业务节点,完成身份集成。
954 lines (830 loc) • 25.4 kB
Markdown
# DNP 统一身份登录 SDK
统一身份登录 SDK - 基于自定义协议调用桌面应用程序进行身份认证
## 功能特性
- 🔐 统一身份认证
- 🖥️ 桌面应用程序集成
- 📱 自定义协议支持
- ⏱️ 智能轮询机制
- 🔄 自动重试机制
- 💪 TypeScript 支持
- 🌐 多环境支持(浏览器、Electron)
<!-- ## 📚 文档链接
- [📋 更新日志](CHANGELOG.md) - 查看版本更新历史
- [🔧 Webpack 兼容性说明](WEBPACK_COMPATIBILITY.md) - 解决构建兼容性问题
- [📦 发布指南](PUBLISH.md) - 项目发布说明 -->
## 安装
```bash
npm install dnp-client
```
或者使用 yarn:
```bash
yarn add dnp-client
```
## 快速开始
### 1. 统一身份登录
```javascript
import { createDnpLogin } from "dnp-client";
const dnpLogin = createDnpLogin({
options: {
baseUrl: `http://your-api-server.com`, // 服务端地址
type: 1, // 1-区域,2-业务
},
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 = () => {
dnp.login();
};
```
### 2. 身份注册
```javascript
import { createDnpRegister } from "dnp-client";
const dnpRegister = createDnpRegister({
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 = () => {
const subject = [
{ name: "countryName", value: "CN" },
{ name: "stateOrProvinceName", value: "江苏" },
{ name: "localityName", value: "南京" },
{ name: "organizationName", value: "数据中心4" },
{ name: "organizationalUnitName", value: "研发部" },
{ name: "commonName", value: "zaq12wsx3edc4rfv5t" },
];
dnpRegister.registerIdentity({ subject: JSON.stringify(subject) });
};
```
### 3. 身份凭证导入
```javascript
import { createDnpImportVc } from "dnp-client";
const dnpImportVc = createDnpImportVc({
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 certData = {
crt, // 证书内容
certType: "1", // 凭证类型 1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证
};
dnpImportVc.importCert(certData);
};
```
## Vue.js 集成示例
### 登录组件
```vue
<template>
<div>
<button @click="handleLogin" :disabled="loading">
{{ loading ? "登录中..." : "统一身份登录" }}
</button>
<div v-if="message">{{ message }}</div>
</div>
</template>
<script>
import { createDnpLogin } from "dnp-client";
export default {
data() {
return {
loading: false,
message: "",
dnpLogin: null,
};
},
created() {
this.dnpLogin = createDnpLogin({
options: {
baseUrl:
process.env.VUE_APP_API_BASE_URL ||
`${window.location.origin}/api/v1`,
},
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.dnpLogin.login();
},
},
beforeDestroy() {
if (this.dnpLogin) {
this.dnpLogin.destroy();
}
},
};
</script>
```
### 注册组件
```vue
<template>
<div>
<button @click="handleRegister" :disabled="loading">
{{ loading ? "注册中..." : "注册数字身份" }}
</button>
<div v-if="message">{{ message }}</div>
</div>
</template>
<script>
import { createDnpRegister } from "dnp-client";
export default {
data() {
return {
loading: false,
message: "",
dnpRegister: null,
};
},
created() {
this.dnpRegister = createDnpRegister({
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() {
// 构建主体信息
const subject = [
{ name: "countryName", value: "CN" },
{ name: "stateOrProvinceName", value: "北京" },
{ name: "localityName", value: "海淀" },
{ name: "organizationName", value: "科技公司" },
{ name: "organizationalUnitName", value: "研发部" },
{ name: "commonName", value: "www.example.com" },
];
this.dnpRegister.registerIdentity({
subject: JSON.stringify(subject),
});
},
},
beforeDestroy() {
if (this.dnpRegister) {
this.dnpRegister.destroy();
}
},
};
</script>
```
### 凭证导入组件
```vue
<template>
<div>
<div class="cert-form">
<h3>身份凭证导入</h3>
<div class="form-group">
<label>证书内容:</label>
<textarea
v-model="certContent"
placeholder="请粘贴证书内容(PEM格式)"
rows="10"
cols="60"
></textarea>
</div>
<div class="form-group">
<label>凭证类型:</label>
<select v-model="certType">
<option value="1">接入主体身份凭证</option>
<option value="2">接入连接器身份凭证</option>
<option value="3">业务节点身份凭证</option>
</select>
</div>
<button @click="handleImport" :disabled="loading || !certContent">
{{ loading ? "导入中..." : "导入凭证" }}
</button>
<button @click="useSampleCert" :disabled="loading">使用示例证书</button>
</div>
<div v-if="message" class="message">{{ message }}</div>
</div>
</template>
<script>
import { createDnpImportVc } from "dnp-client";
export default {
data() {
return {
loading: false,
message: "",
certContent: "",
certType: "1",
dnpImportVc: null,
};
},
created() {
this.dnpImportVc = createDnpImportVc({
callbacks: {
onLoading: (loading) => {
this.loading = loading;
},
onSuccess: (result) => {
this.message = "凭证导入成功!";
console.log("导入结果:", result);
// 处理导入成功逻辑
localStorage.setItem("importedCert", JSON.stringify(result));
},
onError: (error) => {
this.message = `导入失败: ${error.message}`;
},
onMessage: (message, type) => {
this.message = message;
},
},
});
},
methods: {
handleImport() {
if (!this.certContent.trim()) {
this.message = "请输入证书内容";
return;
}
const certData = {
crt: this.certContent, // 证书内容
certType: this.certType, // 凭证类型
};
this.dnpImportVc.importCert(certData);
},
useSampleCert() {
// 使用示例证书
this.certContent = `-----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-----`;
this.message = "已填入示例证书";
},
},
beforeDestroy() {
if (this.dnpImportVc) {
this.dnpImportVc.destroy();
}
},
};
</script>
<style scoped>
.cert-form {
max-width: 600px;
margin: 20px 0;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group textarea {
width: 100%;
border: 1px solid #ddd;
border-radius: 4px;
padding: 8px;
font-family: monospace;
font-size: 12px;
resize: vertical;
}
.form-group select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
margin-right: 10px;
padding: 8px 16px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.message {
margin-top: 15px;
padding: 10px;
border-radius: 4px;
background-color: #f8f9fa;
border: 1px solid #dee2e6;
}
</style>
```
## React 集成示例
### 登录组件
```jsx
import React, { useState, useEffect, useRef } from "react";
import { createDnpLogin } from "dnp-client";
function LoginComponent() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const dnpLoginRef = useRef(null);
useEffect(() => {
dnpLoginRef.current = createDnpLogin({
options: {
baseUrl:
process.env.REACT_APP_API_BASE_URL ||
`${window.location.origin}/api/v1`,
},
callbacks: {
onLoading: setLoading,
onSuccess: (token) => {
setMessage("登录成功!");
localStorage.setItem("authToken", token);
// 跳转到主页或处理登录成功逻辑
},
onError: (error) => {
setMessage(`登录失败: ${error.message}`);
},
onMessage: (message) => {
setMessage(message);
},
},
});
return () => {
if (dnpLoginRef.current) {
dnpLoginRef.current.destroy();
}
};
}, []);
const handleLogin = () => {
dnpLoginRef.current?.login();
};
return (
<div>
<button onClick={handleLogin} disabled={loading}>
{loading ? "登录中..." : "统一身份登录"}
</button>
{message && <div>{message}</div>}
</div>
);
}
export default LoginComponent;
```
### 注册组件
```jsx
import React, { useState, useEffect, useRef } from "react";
import { createDnpRegister } from "dnp-client";
function RegisterComponent() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const dnpRegisterRef = useRef(null);
useEffect(() => {
dnpRegisterRef.current = createDnpRegister({
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}`);
},
onMessage: (message) => {
setMessage(message);
},
},
});
return () => {
if (dnpRegisterRef.current) {
dnpRegisterRef.current.destroy();
}
};
}, []);
const handleRegister = () => {
// 构建主体信息
const subject = [
{ name: "countryName", value: "CN" },
{ name: "stateOrProvinceName", value: "北京" },
{ name: "localityName", value: "海淀" },
{ name: "organizationName", value: "科技公司" },
{ name: "organizationalUnitName", value: "研发部" },
{ name: "commonName", value: "www.example.com" },
];
dnpRegisterRef.current?.registerIdentity({
subject: JSON.stringify(subject),
});
};
return (
<div>
<button onClick={handleRegister} disabled={loading}>
{loading ? "注册中..." : "注册数字身份"}
</button>
{message && <div>{message}</div>}
</div>
);
}
export default RegisterComponent;
```
### 凭证导入组件
```jsx
import React, { useState, useEffect, useRef } from "react";
import { createDnpImportVc } from "dnp-client";
function ImportVcComponent() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const [certContent, setCertContent] = useState("");
const [certType, setCertType] = useState("1");
const dnpImportVcRef = useRef(null);
useEffect(() => {
dnpImportVcRef.current = createDnpImportVc({
callbacks: {
onLoading: setLoading,
onSuccess: (result) => {
setMessage("凭证导入成功!");
console.log("导入结果:", result);
// 处理导入成功逻辑
localStorage.setItem("importedCert", JSON.stringify(result));
},
onError: (error) => {
setMessage(`导入失败: ${error.message}`);
},
onMessage: (message, type) => {
setMessage(message);
},
},
});
return () => {
if (dnpImportVcRef.current) {
dnpImportVcRef.current.destroy();
}
};
}, []);
const handleImport = () => {
if (!certContent.trim()) {
setMessage("请输入证书内容");
return;
}
const certData = {
crt: certContent, // 证书内容
certType: certType, // 凭证类型
};
dnpImportVcRef.current?.importCert(certData);
};
const useSampleCert = () => {
// 使用示例证书
const sampleCert = `-----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-----`;
setCertContent(sampleCert);
setMessage("已填入示例证书");
};
return (
<div>
<div style={{ maxWidth: "600px", margin: "20px 0" }}>
<h3>身份凭证导入</h3>
<div style={{ marginBottom: "15px" }}>
<label
style={{
display: "block",
marginBottom: "5px",
fontWeight: "bold",
}}
>
证书内容:
</label>
<textarea
value={certContent}
onChange={(e) => setCertContent(e.target.value)}
placeholder="请粘贴证书内容(PEM格式)"
rows="10"
cols="60"
style={{
width: "100%",
border: "1px solid #ddd",
borderRadius: "4px",
padding: "8px",
fontFamily: "monospace",
fontSize: "12px",
resize: "vertical",
}}
/>
</div>
<div style={{ marginBottom: "15px" }}>
<label
style={{
display: "block",
marginBottom: "5px",
fontWeight: "bold",
}}
>
凭证类型:
</label>
<select
value={certType}
onChange={(e) => setCertType(e.target.value)}
style={{
width: "100%",
padding: "8px",
border: "1px solid #ddd",
borderRadius: "4px",
}}
>
<option value="1">接入主体身份凭证</option>
<option value="2">接入连接器身份凭证</option>
<option value="3">业务节点身份凭证</option>
</select>
</div>
<button
onClick={handleImport}
disabled={loading || !certContent}
style={{
marginRight: "10px",
padding: "8px 16px",
backgroundColor: loading || !certContent ? "#ccc" : "#007bff",
color: "white",
border: "none",
borderRadius: "4px",
cursor: loading || !certContent ? "not-allowed" : "pointer",
}}
>
{loading ? "导入中..." : "导入凭证"}
</button>
<button
onClick={useSampleCert}
disabled={loading}
style={{
padding: "8px 16px",
backgroundColor: loading ? "#ccc" : "#28a745",
color: "white",
border: "none",
borderRadius: "4px",
cursor: loading ? "not-allowed" : "pointer",
}}
>
使用示例证书
</button>
</div>
{message && (
<div
style={{
marginTop: "15px",
padding: "10px",
borderRadius: "4px",
backgroundColor: "#f8f9fa",
border: "1px solid #dee2e6",
}}
>
{message}
</div>
)}
</div>
);
}
export default ImportVcComponent;
```
## 配置选项
### DnpLoginOptions
| 参数 | 类型 | 默认值 | 说明 |
| --------- | -------- | ------------------------ | ---------------------------- |
| `baseUrl` | `string` | `window.location.origin` | 域名配置(用于桌面应用调用) |
| `type` | `number` | `1` | 类型参数 1-区域,2-业务 |
### DnpLoginCallbacks
| 参数 | 类型 | 说明 |
| ----------- | ------------------------------------------ | ---------------------- |
| `onLoading` | `(loading: boolean) => void` | 加载状态变化回调 |
| `onSuccess` | `(data: any) => void` | 成功回调,返回相应数据 |
| `onError` | `(error: Error) => void` | 错误回调 |
| `onMessage` | `(message: string, type?: string) => void` | 消息回调 |
### 身份凭证数据结构
```javascript
const certData = {
crt: "string", // 证书内容-----BEGIN CERTIFICATE-----\nXXX-----END CERTIFICATE-----
certType: "1", // 凭证类型 1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证
};
```
## API 方法
### 登录相关
#### `login()`
开始统一身份登录流程。
```javascript
await dnpLogin.login();
```
### 注册相关
#### `registerIdentity(params)`
注册身份(1-接入主体身份凭证 2-接入连接器身份凭证 3-业务节点身份凭证)。
```javascript
// 注册
await dnpRegister.registerIdentity({
subject: "[{ name: 'countryName', value: 'CN' }]",
});
```
参数说明:
- `subject` (必填): 主体信息
### 凭证导入相关
#### `importCert(certData)`
导入身份凭证。
```javascript
await dnpImportVc.importCert(certData);
```
## 工厂函数
### `createDnpLogin(config)`
创建登录实例。
```javascript
import { createDnpLogin } from "dnp-client";
const dnpLogin = createDnpLogin(config);
```
### `createDnpRegister(config)`
创建注册实例。
```javascript
import { createDnpRegister } from "dnp-client";
const dnpRegister = createDnpRegister(config);
```
### `createDnpImportVc(config)`
创建凭证导入实例。
```javascript
import { createDnpImportVc } from "dnp-client";
const dnpImportVc = createDnpImportVc(config);
```
## 注意事项
1. **桌面应用依赖**:此 SDK 依赖于桌面应用程序,需要确保目标设备已安装相应的桌面客户端
2. **自定义协议**:自定义协议 `dnp://` 需要在桌面应用程序中正确注册
3. **服务器配置**:确保 DNP 服务器正确配置并运行在指定端口(默认 3521)
4. **资源清理**:建议在组件销毁时调用 `destroy()` 方法以释放资源
5. **错误处理**:建议实现完整的错误处理机制,包括网络错误、超时等情况
## 错误处理
### 常见错误情况
- 网络连接失败
- 服务器响应错误
- 桌面应用程序未安装
- 自定义协议未注册
- 轮询超时
### 错误处理建议
```javascript
const dnpLogin = createDnpLogin({
callbacks: {
onError: (error) => {
console.error("DNP错误:", error);
// 根据错误类型进行处理
if (error.message.includes("fetch")) {
// 网络错误
alert("网络连接失败,请检查网络设置");
} else if (error.message.includes("timeout")) {
// 超时错误
alert("操作超时,请重试");
} else {
// 其他错误
alert("操作失败,请重试");
}
},
onMessage: (message, type) => {
if (type === "error") {
console.error("DNP消息:", message);
}
},
},
});
```
## 浏览器兼容性
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- 支持现代浏览器的自定义协议处理
## 许可证
MIT License
## 贡献
欢迎提交 Issue 和 Pull Request 来改进这个项目。