# 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 ``` #### 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 ```