前置环境准备
本文适配Ubuntu 20.04/Windows 10以上系统,所有依赖直接获取安装,无额外隐藏步骤:
- Git:Windows直接下载安装
https://github.com/git-for-windows/git/releases/download/v2.39.1.windows.1/Git-2.39.1-64-bit.exe,Ubuntu执行命令:sudo apt update && sudo apt install git -y
- Node.js 16:Windows直接下载安装
https://nodejs.org/dist/v16.18.0/node-v16.18.0-x64.msi,Ubuntu执行命令:curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - && sudo apt-get install -y nodejs
- Java JDK 1.8:Windows下载地址
https://cdn.azul.com/zulu/bin/zulu8.66.0.15-ca-jdk8.0.352-win_x64.zip,Ubuntu执行命令:sudo apt install openjdk-8-jdk -y
第一步:搭建本地区块链节点
选用适配政务场景的FISCO BCOS联盟链作为底层,执行以下命令一键完成搭建:
```
curl -LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.9.1/build_chain.sh && chmod u+x build_chain.sh
bash build_chain.sh -l 127.0.0.1:1 -p 30300,20200,8545
```
执行完成后启动节点:
```
cd nodes/127.0.0.1 && bash start_all.sh
```
验证节点状态:执行tail -f nodes/127.0.0.1/node0/log/log | grep connected,输出connected to 127.0.0.1:30300即节点正常运行。Windows用户可通过WSL执行上述命令,操作完全一致。
第二步:部署电子档案存证合约
1. 准备智能合约代码
新建文件ArchiveProof.sol,复制以下完整合约,仅存储档案哈希保护隐私,功能完整可直接使用:
```
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
contract ArchiveProof {
struct Archive {
string archiveHash; // 电子档案原文SHA-256哈希
string archiveId; // 数字档案馆系统档案编号
address uploader; // 存证发起地址
uint256 timestamp; // 区块存证时间
string orgCode; // 存档机构编码
}
mapping(string => Archive) public archives;
event ArchiveStored(string indexed archiveId, uint256 timestamp);
function storeArchive(string memory _archiveId, string memory _archiveHash, string memory _orgCode) public {
Archive storage newArchive = archives[_archiveId];
newArchive.archiveId = _archiveId;
newArchive.archiveHash = _archiveHash;
newArchive.uploader = msg.sender;
newArchive.timestamp = block.timestamp;
newArchive.orgCode = _orgCode;
emit ArchiveStored(_archiveId, block.timestamp);
}
function getArchive(string memory _archiveId) public view returns(Archive memory) {
return archives[_archiveId];
}
}
```
2. 部署合约到区块链节点
拉取FISCO BCOS控制台并完成配置,执行以下命令:
```
cd ~ && git clone https://github.com/FISCO-BCOS/console.git && cd console && cp -r ~/nodes/127.0.0.1/sdk/ conf/
./gradlew build -x test
```

启动控制台后输入deploy ArchiveProof.sol,等待部署完成后,记录输出的合约地址,后续对接业务系统需要使用。
第三步:对接数字档案馆业务接口
新建业务项目目录,初始化并安装依赖:
```
mkdir ~/archive-dapp && cd ~/archive-dapp && npm init -y && npm install web3 crypto-js express cors --save
```
新建app.js文件,复制以下完整代码,将代码中的YOUR_CONTRACT_ADDRESS替换为上一步记录的合约地址:
```
const express = require('express');
const Web3 = require('web3');
const SHA256 = require('crypto-js/sha256');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
// 连接本地区块链节点
const web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545'));
const contractAbi = [{"inputs":[{"internalType":"string","name":"_archiveId","type":"string"},{"internalType":"string","name":"_archiveHash","type":"string"},{"internalType":"string","name":"_orgCode","type":"string"}],"name":"storeArchive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_archiveId","type":"string"}],"name":"getArchive","outputs":[{"components":[{"internalType":"string","name":"archiveHash","type":"string"},{"internalType":"string","name":"archiveId","type":"string"},{"internalType":"address","name":"uploader","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"string","name":"orgCode","type":"string"}],"internalType":"struct ArchiveProof.Archive","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}];
const contractAddress = 'YOUR_CONTRACT_ADDRESS';
const archiveContract = new web3.eth.Contract(contractAbi, contractAddress);
const adminAccount = web3.eth.accounts[0];
// 档案存证接口
app.post('/upload', async (req, res) => {
const { archiveId, orgCode, fileContent } = req.body;
// 计算档案原文哈希
const archiveHash = SHA256(fileContent).toString();
try {
const receipt = await archiveContract.methods.storeArchive(archiveId, archiveHash, orgCode).send({from: adminAccount, gas: 1000000});
res.json({code: 0, msg: '存证成功', txHash: receipt.transactionHash, archiveHash: archiveHash});
} catch (err) {
res.json({code: 1, msg: '存证失败: ' + err.message});
}
});
// 档案查询验证接口
app.get('/query', async (req, res) => {
const { archiveId } = req.query;
const archive = await archiveContract.methods.getArchive(archiveId).call();
res.json({code:0, data: archive});
});
app.listen(3000, () => {
console.log('业务服务已启动,访问地址 http://localhost:3000');
});
```
启动业务服务,执行命令:node app.js,服务启动后即可调用接口。
第四步:功能验证
打开终端执行以下命令测试存证功能:
```
curl -X POST http://localhost:3000/upload -H "Content-Type: application/json" -d '{"archiveId":"DA20240001","orgCode":"010001","fileContent":"2024年度单位民生项目档案原文"}'
```
返回成功结果后,执行查询验证:
```
curl http://localhost:3000/query?archiveId=DA20240001
```
即可返回链上存储的完整档案信息,如需验证防篡改,修改原文后重新计算哈希,对比链上存储的哈希即可发现不一致,完成篡改验证。
生产环境落地注意事项
- 多节点部署:生产环境需要每个参与档案管理的单位部署独立节点,组成多群组联盟链,官方部署文档:
https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/installation.html
- 数据规范:仅将档案哈希上链,原文存储在数字档案馆本地涉密存储系统,符合档案保密管理要求
- 权限控制:业务层需要对接档案馆现有统一身份认证系统,仅授权管理员可发起存证操作