|
|
|
# Spiderman - Hyperledger Fabric Asset Transfer REST API
|
|
|
|
|
|
|
|
这是一个基于Hyperledger Fabric的资产转移REST API服务,代号为Spiderman,提供了完整的RESTful接口来管理区块链上的资产。
|
|
|
|
|
|
|
|
## 功能特性
|
|
|
|
|
|
|
|
- 初始化账本
|
|
|
|
- 创建资产
|
|
|
|
- 查询所有资产
|
|
|
|
- 根据ID查询资产
|
|
|
|
- 转移资产所有权
|
|
|
|
- 更新资产信息
|
|
|
|
- **完整的Swagger API文档**
|
|
|
|
- **交互式API测试界面**
|
|
|
|
|
|
|
|
## 先决条件
|
|
|
|
|
|
|
|
1. Go 1.23.0 或更高版本
|
|
|
|
2. Hyperledger Fabric网络已运行
|
|
|
|
3. 正确配置的证书和密钥文件
|
|
|
|
|
|
|
|
## 安装和运行
|
|
|
|
|
|
|
|
1. 下载依赖项:
|
|
|
|
```bash
|
|
|
|
go mod tidy
|
|
|
|
```
|
|
|
|
|
|
|
|
2. 启动服务:
|
|
|
|
```bash
|
|
|
|
go run .
|
|
|
|
```
|
|
|
|
|
|
|
|
服务默认在端口8080上运行,可以通过环境变量`PORT`自定义端口。
|
|
|
|
|
|
|
|
## API 接口
|
|
|
|
|
|
|
|
### 基础URL
|
|
|
|
```
|
|
|
|
http://localhost:8080/api/v1
|
|
|
|
```
|
|
|
|
|
|
|
|
### 🔍 Swagger API 文档
|
|
|
|
|
|
|
|
**访问地址:** `http://localhost:8080/swagger/index.html`
|
|
|
|
|
|
|
|
Swagger提供完整的API文档和交互式测试界面,您可以:
|
|
|
|
- 查看所有API端点的详细信息
|
|
|
|
- 在线测试API接口
|
|
|
|
- 查看请求/响应示例
|
|
|
|
- 下载API规范文件(JSON/YAML)
|
|
|
|
|
|
|
|
### 健康检查
|
|
|
|
```http
|
|
|
|
GET /health
|
|
|
|
```
|
|
|
|
|
|
|
|
### 1. 初始化账本
|
|
|
|
初始化区块链账本,创建初始资产集合。
|
|
|
|
|
|
|
|
```http
|
|
|
|
POST /api/v1/ledger/init
|
|
|
|
```
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"message": "Ledger initialized successfully"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 2. 获取所有资产
|
|
|
|
查询账本上的所有资产。
|
|
|
|
|
|
|
|
```http
|
|
|
|
GET /api/v1/assets
|
|
|
|
```
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"data": [
|
|
|
|
{
|
|
|
|
"ID": "asset1",
|
|
|
|
"color": "blue",
|
|
|
|
"size": "5",
|
|
|
|
"owner": "Tomoko",
|
|
|
|
"appraisedValue": "1000"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 3. 创建资产
|
|
|
|
创建一个新的资产。
|
|
|
|
|
|
|
|
```http
|
|
|
|
POST /api/v1/assets
|
|
|
|
```
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"id": "asset123",
|
|
|
|
"color": "red",
|
|
|
|
"size": "10",
|
|
|
|
"owner": "Alice",
|
|
|
|
"appraisedValue": "2000"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"message": "Asset created successfully",
|
|
|
|
"data": {
|
|
|
|
"ID": "asset123",
|
|
|
|
"color": "red",
|
|
|
|
"size": "10",
|
|
|
|
"owner": "Alice",
|
|
|
|
"appraisedValue": "2000"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 4. 根据ID查询资产
|
|
|
|
根据资产ID查询特定资产。
|
|
|
|
|
|
|
|
```http
|
|
|
|
GET /api/v1/assets/{id}
|
|
|
|
```
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"data": {
|
|
|
|
"ID": "asset123",
|
|
|
|
"color": "red",
|
|
|
|
"size": "10",
|
|
|
|
"owner": "Alice",
|
|
|
|
"appraisedValue": "2000"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 5. 转移资产所有权
|
|
|
|
转移资产的所有权给新的拥有者。
|
|
|
|
|
|
|
|
```http
|
|
|
|
PUT /api/v1/assets/{id}/transfer
|
|
|
|
```
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"newOwner": "Bob"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"message": "Asset asset123 transferred to Bob successfully"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 6. 更新资产
|
|
|
|
更新现有资产的信息。
|
|
|
|
|
|
|
|
```http
|
|
|
|
PUT /api/v1/assets/{id}
|
|
|
|
```
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"color": "green",
|
|
|
|
"size": "15",
|
|
|
|
"owner": "Charlie",
|
|
|
|
"appraisedValue": "3000"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"message": "Asset updated successfully",
|
|
|
|
"data": {
|
|
|
|
"ID": "asset123",
|
|
|
|
"color": "green",
|
|
|
|
"size": "15",
|
|
|
|
"owner": "Charlie",
|
|
|
|
"appraisedValue": "3000"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## API 端点
|
|
|
|
|
|
|
|
### 健康检查
|
|
|
|
- `GET /health` - 检查服务健康状态
|
|
|
|
|
|
|
|
### 账本操作
|
|
|
|
- `POST /api/v1/ledger/init` - 初始化账本
|
|
|
|
|
|
|
|
### 资产操作
|
|
|
|
- `GET /api/v1/assets` - 获取所有资产
|
|
|
|
- `POST /api/v1/assets` - 创建新资产
|
|
|
|
- `GET /api/v1/assets/{id}` - 根据ID获取资产
|
|
|
|
- `PUT /api/v1/assets/{id}` - 更新资产信息
|
|
|
|
- `PUT /api/v1/assets/{id}/transfer` - 转移资产所有权
|
|
|
|
|
|
|
|
### 区块链操作
|
|
|
|
- `GET /api/v1/blockchain/height` - 获取当前区块高度
|
|
|
|
- `GET /api/v1/blockchain/info` - 获取区块链信息
|
|
|
|
|
|
|
|
### 交易操作
|
|
|
|
- `GET /api/v1/transactions/{txid}` - 根据交易ID查询交易详情
|
|
|
|
|
|
|
|
### 使用示例
|
|
|
|
|
|
|
|
#### 获取区块高度
|
|
|
|
```bash
|
|
|
|
curl -X GET "http://localhost:8080/api/v1/blockchain/height"
|
|
|
|
```
|
|
|
|
|
|
|
|
响应示例:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"message": "Block height retrieved successfully",
|
|
|
|
"data": {
|
|
|
|
"height": 12345
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### 获取区块链信息
|
|
|
|
```bash
|
|
|
|
curl -X GET "http://localhost:8080/api/v1/blockchain/info"
|
|
|
|
```
|
|
|
|
|
|
|
|
响应示例:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"message": "Chain information retrieved successfully",
|
|
|
|
"data": {
|
|
|
|
"height": 12345,
|
|
|
|
"chainName": "mychannel"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### 查询交易详情
|
|
|
|
```bash
|
|
|
|
curl -X GET "http://localhost:8080/api/v1/transactions/{txid}"
|
|
|
|
```
|
|
|
|
|
|
|
|
响应示例:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": true,
|
|
|
|
"message": "Transaction details retrieved successfully",
|
|
|
|
"data": {
|
|
|
|
"transactionId": "d341d13093e72e201f73725b4d93b45b2e261fd7440e3e624f141f6f8d509495",
|
|
|
|
"blockNumber": 79,
|
|
|
|
"blockHash": "block-hash-for-d341d130",
|
|
|
|
"timestamp": "2025-06-12T13:38:14+08:00",
|
|
|
|
"channelId": "mychannel",
|
|
|
|
"creatorMspId": "",
|
|
|
|
"creatorId": "",
|
|
|
|
"endorsers": null,
|
|
|
|
"chaincodeId": "",
|
|
|
|
"function": "",
|
|
|
|
"arguments": null,
|
|
|
|
"response": {
|
|
|
|
"status": 200,
|
|
|
|
"message": "Transaction completed successfully",
|
|
|
|
"payload": ""
|
|
|
|
},
|
|
|
|
"validationCode": "VALID",
|
|
|
|
"rawTransaction": {
|
|
|
|
"hasData": true,
|
|
|
|
"size": 4822
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## 错误处理
|
|
|
|
|
|
|
|
API使用标准HTTP状态码表示请求结果:
|
|
|
|
|
|
|
|
- `200 OK` - 请求成功
|
|
|
|
- `201 Created` - 资源创建成功
|
|
|
|
- `400 Bad Request` - 请求参数错误
|
|
|
|
- `404 Not Found` - 资源未找到
|
|
|
|
- `500 Internal Server Error` - 服务器内部错误
|
|
|
|
|
|
|
|
错误响应格式:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"success": false,
|
|
|
|
"message": "错误描述信息"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## 配置
|
|
|
|
|
|
|
|
服务使用以下环境变量进行配置:
|
|
|
|
|
|
|
|
- `PORT` - 服务端口(默认:8080)
|
|
|
|
- `CHAINCODE_NAME` - 链码名称(默认:basic)
|
|
|
|
- `CHANNEL_NAME` - 通道名称(默认:mychannel)
|
|
|
|
|
|
|
|
## 证书配置
|
|
|
|
|
|
|
|
确保以下路径存在正确的证书文件:
|
|
|
|
|
|
|
|
- `../../test-network/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts`
|
|
|
|
- `../../test-network/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore`
|
|
|
|
- `../../test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt`
|
|
|
|
|
|
|
|
## 使用示例
|
|
|
|
|
|
|
|
使用curl测试API:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
# 健康检查
|
|
|
|
curl http://localhost:8080/health
|
|
|
|
|
|
|
|
# 初始化账本
|
|
|
|
curl -X POST http://localhost:8080/api/v1/ledger/init
|
|
|
|
|
|
|
|
# 创建资产
|
|
|
|
curl -X POST http://localhost:8080/api/v1/assets \
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
-d '{
|
|
|
|
"id": "asset123",
|
|
|
|
"color": "red",
|
|
|
|
"size": "10",
|
|
|
|
"owner": "Alice",
|
|
|
|
"appraisedValue": "2000"
|
|
|
|
}'
|
|
|
|
|
|
|
|
# 查询所有资产
|
|
|
|
curl http://localhost:8080/api/v1/assets
|
|
|
|
|
|
|
|
# 查询特定资产
|
|
|
|
curl http://localhost:8080/api/v1/assets/asset123
|
|
|
|
|
|
|
|
# 转移资产
|
|
|
|
curl -X PUT http://localhost:8080/api/v1/assets/asset123/transfer \
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
-d '{"newOwner": "Bob"}'
|
|
|
|
```
|
|
|
|
|
|
|
|
## 容器化部署
|
|
|
|
|
|
|
|
### 使用Docker构建和运行
|
|
|
|
|
|
|
|
```bash
|
|
|
|
# 构建镜像
|
|
|
|
docker build -t spiderman -f docker/Dockerfile .
|
|
|
|
|
|
|
|
# 运行容器
|
|
|
|
docker run -p 8080:8080 spiderman
|
|
|
|
```
|
|
|
|
|
|
|
|
### 使用Docker Compose
|
|
|
|
|
|
|
|
```bash
|
|
|
|
# 启动服务
|
|
|
|
cd docker && docker-compose up -d
|
|
|
|
|
|
|
|
# 查看日志
|
|
|
|
cd docker && docker-compose logs -f
|
|
|
|
|
|
|
|
# 停止服务
|
|
|
|
cd docker && docker-compose down
|
|
|
|
```
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
|
|
```
|
|
|
|
.
|
|
|
|
├── main.go # 主服务入口和路由配置
|
|
|
|
├── fabric_client.go # Fabric客户端封装
|
|
|
|
├── api_handler.go # HTTP请求处理器
|
|
|
|
├── docs/ # Swagger生成的API文档
|
|
|
|
│ ├── docs.go # Go文档
|
|
|
|
│ ├── swagger.json # JSON格式API规范
|
|
|
|
│ └── swagger.yaml # YAML格式API规范
|
|
|
|
├── go.mod # Go模块配置
|
|
|
|
├── go.sum # 依赖项校验和
|
|
|
|
├── docker/ # Docker相关文件
|
|
|
|
│ ├── Dockerfile # Docker镜像构建文件
|
|
|
|
│ ├── docker-compose.yml # Docker Compose配置
|
|
|
|
│ └── DOCKER_GUIDE.md # Docker使用指南
|
|
|
|
├── start.sh # 启动脚本
|
|
|
|
├── test_api.sh # API测试脚本
|
|
|
|
└── README.md # 项目文档
|
|
|
|
```
|
|
|
|
|
|
|
|
## 📖 Swagger 配置
|
|
|
|
|
|
|
|
本项目的 Swagger 文档配置现在支持通过 `config.env` 文件动态设置 host 和 port。
|
|
|
|
|
|
|
|
### 配置方式
|
|
|
|
|
|
|
|
在 `config.env` 文件中设置以下参数:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
# Server Configuration
|
|
|
|
HOST=localhost # Swagger 文档的主机地址
|
|
|
|
PORT=8888 # Swagger 文档的端口号
|
|
|
|
```
|
|
|
|
|
|
|
|
### 访问地址
|
|
|
|
|
|
|
|
启动服务后,Swagger 文档将在以下地址可用:
|
|
|
|
- Swagger UI: `http://{HOST}:{PORT}/swagger/index.html`
|
|
|
|
- API 基础路径: `http://{HOST}:{PORT}/api/v1`
|
|
|
|
|
|
|
|
例如,使用默认配置时:
|
|
|
|
- Swagger UI: http://localhost:8888/swagger/index.html
|
|
|
|
- API 基础路径: http://localhost:8888/api/v1
|
|
|
|
|
|
|
|
### 自定义配置示例
|
|
|
|
|
|
|
|
如果你需要在不同的主机或端口上运行:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
# config.env
|
|
|
|
HOST=192.168.1.100
|
|
|
|
PORT=9090
|
|
|
|
```
|
|
|
|
|
|
|
|
服务启动后会自动更新 Swagger 配置,无需手动重新生成文档。
|
|
|
|
|
|
|
|
## 🔧 故障排除
|
|
|
|
|
|
|
|
### API访问错误解决方案
|
|
|
|
|
|
|
|
如果在使用curl访问API时遇到错误,请按以下步骤排查:
|
|
|
|
|
|
|
|
#### 1. JSON反序列化错误
|
|
|
|
**错误信息**: `cannot unmarshal number into Go struct field Asset.appraisedValue of type string`
|
|
|
|
|
|
|
|
**原因**: Hyperledger Fabric链码中的初始数据的`appraisedValue`字段是数字类型,但API代码期望字符串类型。
|
|
|
|
|
|
|
|
**解决方案**: 已在`pkg/models/asset.go`中实现自定义JSON反序列化方法:
|
|
|
|
|
|
|
|
```go
|
|
|
|
// 自定义UnmarshalJSON方法处理数字和字符串类型的appraisedValue
|
|
|
|
func (a *Asset) UnmarshalJSON(data []byte) error {
|
|
|
|
// 支持string, float64, int, int64类型的自动转换
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### 2. gRPC连接超时错误
|
|
|
|
**错误信息**: `gRPC error: context deadline exceeded`
|
|
|
|
|
|
|
|
**原因**: Hyperledger Fabric网络没有运行或配置不正确。
|
|
|
|
|
|
|
|
**解决方案**:
|
|
|
|
1. 确保Fabric网络正在运行:
|
|
|
|
```bash
|
|
|
|
# 在fabric-samples/test-network目录下
|
|
|
|
./network.sh up createChannel -ca -c mychannel
|
|
|
|
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
|
|
|
|
```
|
|
|
|
|
|
|
|
2. 检查网络状态:
|
|
|
|
```bash
|
|
|
|
docker ps # 应该看到peer, orderer, ca等容器
|
|
|
|
```
|
|
|
|
|
|
|
|
3. 验证配置文件中的路径:
|
|
|
|
```bash
|
|
|
|
# config.env中的CRYPTO_PATH是否指向正确的证书目录
|
|
|
|
CRYPTO_PATH=../../test-network/organizations/peerOrganizations/org1.example.com
|
|
|
|
```
|
|
|
|
|
|
|
|
#### 3. 端口冲突
|
|
|
|
**错误信息**: `bind: address already in use`
|
|
|
|
|
|
|
|
**解决方案**:
|
|
|
|
```bash
|
|
|
|
# 查找占用端口的进程
|
|
|
|
lsof -i :8888
|
|
|
|
# 停止进程
|
|
|
|
kill -9 <PID>
|
|
|
|
```
|
|
|
|
|
|
|
|
#### 4. 证书路径错误
|
|
|
|
**错误信息**: `failed to read certificate file` 或 `failed to read private key file`
|
|
|
|
|
|
|
|
**解决方案**:
|
|
|
|
1. 检查证书路径是否存在:
|
|
|
|
```bash
|
|
|
|
ls -la ../../test-network/organizations/peerOrganizations/org1.example.com/
|
|
|
|
```
|
|
|
|
|
|
|
|
2. 确保当前目录正确:
|
|
|
|
```bash
|
|
|
|
pwd # 应该在项目根目录
|
|
|
|
```
|
|
|
|
|
|
|
|
### 测试API连接
|
|
|
|
|
|
|
|
1. **健康检查**:
|
|
|
|
```bash
|
|
|
|
curl http://localhost:8888/health
|
|
|
|
```
|
|
|
|
|
|
|
|
2. **初始化账本** (首次使用):
|
|
|
|
```bash
|
|
|
|
curl -X POST http://localhost:8888/api/v1/ledger/init
|
|
|
|
```
|
|
|
|
|
|
|
|
3. **获取所有资产**:
|
|
|
|
```bash
|
|
|
|
curl http://localhost:8888/api/v1/assets
|
|
|
|
```
|
|
|
|
|
|
|
|
### 常见问题
|
|
|
|
|
|
|
|
**Q: API返回空数组`{"success":true,"data":[]}`?**
|
|
|
|
A: 账本可能没有初始化,运行初始化命令:
|
|
|
|
```bash
|
|
|
|
curl -X POST http://localhost:8888/api/v1/ledger/init
|
|
|
|
```
|
|
|
|
|
|
|
|
**Q: Swagger UI无法访问?**
|
|
|
|
A: 确保在开发环境下运行:
|
|
|
|
```bash
|
|
|
|
ENVIRONMENT=development go run cmd/server/main.go
|
|
|
|
```
|
|
|
|
|
|
|
|
**Q: 修改代码后错误依然存在?**
|
|
|
|
A: 清理缓存并重新启动:
|
|
|
|
```bash
|
|
|
|
go clean -cache
|
|
|
|
go mod tidy
|
|
|
|
go run cmd/server/main.go
|
|
|
|
```
|