REST API bridge service for ZKTeco fingerprint devices using Pull SDK. This service allows you to connect to ZKTeco devices (like MVL10) from any programming language via HTTP REST API.
- ✅ Connect/Disconnect to ZKTeco devices via TCP/IP
- ✅ User Management (Add, Get, Delete)
- ✅ Fingerprint Management (Upload, Get, Delete templates)
- ✅ Real-time Access Log Monitoring
- ✅ Attendance Log Retrieval
- ✅ Device Information & Status
- ✅ Device Control (Unlock doors, trigger outputs)
- ✅ Network Device Discovery
- ✅ CORS enabled for web applications
- ✅ Comprehensive error handling
- ✅ Request validation
- Java 17
- Spring Boot 3.2.0
- JNA (Java Native Access) for DLL integration
- Lombok for cleaner code
- Maven for dependency management
-
Java Development Kit (JDK) 17 or higher
- Download: https://adoptium.net/
-
Maven 3.6+
- Download: https://maven.apache.org/download.cgi
- Or use IntelliJ IDEA / Eclipse which includes Maven
-
ZKTeco Pull SDK DLLs (included in this project)
- Located in:
/pull_sdk/SDK-Ver2.2.0.220/ - Required DLLs:
plcommpro.dll(main SDK)pltcpcomm.dll(TCP communication)plrscomm.dll(RS485 communication)plusbcomm.dll(USB communication)- Other supporting DLLs
- Located in:
-
Windows Operating System (required for DLLs)
- Windows 10/11 recommended
- Windows Server 2016+ supported
-
ZKTeco Device (e.g., MVL10)
- Connected to same network
- IP address accessible
- Port 4370 open (default)
# Navigate to project directory
cd zkteco-java-bridge
# Create dll directory
mkdir dll
# Copy all DLLs from Pull SDK
cp ../pull_sdk/SDK-Ver2.2.0.220/*.dll ./dll/Important: The application looks for DLLs in these locations (in order):
ZKTECO_DLL_PATHenvironment variable./dll/directory (relative to project)- Pull SDK path:
~/Desktop/zlink_java_code/pull_sdk/SDK-Ver2.2.0.220/
# Using Maven
mvn clean package
# Or if using Maven wrapper
./mvnw clean packageThis will create: target/zkteco-bridge-1.0.0.jar
Option A: Using Maven
mvn spring-boot:runOption B: Using JAR file
java -jar target/zkteco-bridge-1.0.0.jarOption C: With custom DLL path
# Windows
set ZKTECO_DLL_PATH=C:\path\to\dlls
java -jar target/zkteco-bridge-1.0.0.jar
# Or inline
java -Djna.library.path=C:\path\to\dlls -jar target/zkteco-bridge-1.0.0.jarOption D: Using IDE
- Open project in IntelliJ IDEA or Eclipse
- Right-click on
Application.java - Select "Run Application"
# Health check
curl http://localhost:8080/api/device/health
# Expected response:
{
"status": "UP",
"service": "ZKTeco Bridge",
"version": "1.0.0",
"connected": false
}Edit src/main/resources/application.properties:
# Change port (default: 8080)
server.port=8080
# Logging level
logging.level.com.zkteco.bridge=DEBUGZKTECO_DLL_PATH- Path to DLL filesSERVER_PORT- Override server port
Base URL: http://localhost:8080/api/device
POST /connect
curl -X POST http://localhost:8080/api/device/connect \
-H "Content-Type: application/json" \
-d '{
"ip": "192.168.1.201",
"port": 4370,
"timeout": 4000
}'Response:
{
"success": true,
"message": "Connected to device at 192.168.1.201",
"data": {
"ip": "192.168.1.201",
"port": 4370,
"connected": true
}
}POST /disconnect
curl -X POST http://localhost:8080/api/device/disconnectGET /status
curl http://localhost:8080/api/device/statusResponse:
{
"success": true,
"message": "Status retrieved",
"data": {
"connected": true,
"deviceIp": "192.168.1.201"
}
}POST /user
curl -X POST http://localhost:8080/api/device/user \
-H "Content-Type: application/json" \
-d '{
"pin": "1001",
"cardNo": "12345",
"name": "John Doe",
"password": "",
"group": 1
}'Response:
{
"success": true,
"message": "User added successfully",
"data": {
"pin": "1001",
"cardNo": "12345",
"recordsAffected": 1
}
}GET /users
curl http://localhost:8080/api/device/usersResponse:
{
"success": true,
"message": "Users retrieved successfully",
"data": {
"users": [
{
"CardNo": "12345",
"Pin": "1001",
"Password": "",
"Group": "1"
}
],
"count": 1
}
}DELETE /user/{pin}
curl -X DELETE http://localhost:8080/api/device/user/1001POST /fingerprint
curl -X POST http://localhost:8080/api/device/fingerprint \
-H "Content-Type: application/json" \
-d '{
"pin": "1001",
"fingerID": 0,
"template": "BASE64_ENCODED_TEMPLATE_DATA",
"valid": 1
}'Response:
{
"success": true,
"message": "Fingerprint uploaded successfully",
"data": {
"pin": "1001",
"fingerID": 0,
"recordsAffected": 1
}
}GET /fingerprint/{pin}
curl http://localhost:8080/api/device/fingerprint/1001DELETE /fingerprint/{pin}?fingerID=0
curl -X DELETE "http://localhost:8080/api/device/fingerprint/1001?fingerID=0"GET /rtlog
curl http://localhost:8080/api/device/rtlogResponse:
{
"success": true,
"message": "Log entry retrieved",
"data": {
"log": {
"cardNo": "12345",
"pin": "1001",
"verified": "1",
"doorID": "1",
"eventType": "0",
"inOutState": "0",
"time": "1642156800"
}
}
}GET /info
curl http://localhost:8080/api/device/infoResponse:
{
"success": true,
"message": "Device info retrieved",
"data": {
"DeviceID": "1",
"DateTime": "2024-01-15 10:30:00",
"LockCount": "4",
"ReaderCount": "2"
}
}GET /logs?filter=Pin=1001
# All logs
curl http://localhost:8080/api/device/logs
# Filtered by user
curl "http://localhost:8080/api/device/logs?filter=Pin=1001"POST /control
# Unlock door 1 for 5 seconds
curl -X POST http://localhost:8080/api/device/control \
-H "Content-Type: application/json" \
-d '{
"operationId": 1,
"param1": 1,
"param2": 1,
"param3": 5,
"param4": 0
}'Operation IDs:
1= Output control (unlock door, trigger relay)4= Door normal open/close control
GET /search
curl http://localhost:8080/api/device/searchnpm install axiosCreate services/zktecoService.js:
const axios = require('axios');
const JAVA_BRIDGE_URL = process.env.JAVA_BRIDGE_URL || 'http://localhost:8080/api/device';
class ZKTecoService {
async connect(ip, port = 4370, timeout = 4000) {
const response = await axios.post(`${JAVA_BRIDGE_URL}/connect`, {
ip, port, timeout
});
return response.data;
}
async disconnect() {
const response = await axios.post(`${JAVA_BRIDGE_URL}/disconnect`);
return response.data;
}
async addUser(pin, cardNo, name, password = '', group = 1) {
const response = await axios.post(`${JAVA_BRIDGE_URL}/user`, {
pin, cardNo, name, password, group
});
return response.data;
}
async getUsers() {
const response = await axios.get(`${JAVA_BRIDGE_URL}/users`);
return response.data;
}
async uploadFingerprint(pin, fingerID, template) {
const response = await axios.post(`${JAVA_BRIDGE_URL}/fingerprint`, {
pin, fingerID, template, valid: 1
});
return response.data;
}
async getRealTimeLog() {
const response = await axios.get(`${JAVA_BRIDGE_URL}/rtlog`);
return response.data;
}
}
module.exports = new ZKTecoService();const express = require('express');
const zkService = require('./services/zktecoService');
const router = express.Router();
router.post('/connect', async (req, res) => {
const { ip, port } = req.body;
const result = await zkService.connect(ip, port);
res.json(result);
});
router.post('/users', async (req, res) => {
const { pin, cardNo, name } = req.body;
const result = await zkService.addUser(pin, cardNo, name);
res.json(result);
});
module.exports = router;Solution:
- Verify DLLs are in
./dll/directory - Check file permissions
- Set
ZKTECO_DLL_PATHenvironment variable - Ensure you're running on Windows
Solution:
- Check device IP address is correct
- Verify device is on same network
- Test connectivity:
ping 192.168.1.201 - Check port 4370 is not blocked by firewall
- Verify device is powered on
Solution:
- Ensure device is connected first
- Check user PIN doesn't already exist
- Verify PIN format (usually numeric)
- Check device memory is not full
Solution:
# Change port in application.properties
server.port=8081
# Or set environment variable
set SERVER_PORT=8081
java -jar target/zkteco-bridge-1.0.0.jarEdit application.properties:
logging.level.com.zkteco.bridge=DEBUG
logging.level.com.sun.jna=DEBUG┌─────────────────────────────────────────────┐
│ Frontend / Node.js Backend │
└─────────────────┬───────────────────────────┘
│ HTTP REST API
│
┌─────────────────▼───────────────────────────┐
│ ZKTeco Java Bridge (Spring Boot) │
│ ┌──────────────────────────────────────┐ │
│ │ REST Controllers │ │
│ └──────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────▼───────────────────────────┐ │
│ │ Service Layer (Business) │ │
│ └──────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────▼───────────────────────────┐ │
│ │ JNA Interface (PullSDK.java) │ │
│ └──────────┬───────────────────────────┘ │
└─────────────┼───────────────────────────────┘
│ JNI/JNA
┌─────────────▼───────────────────────────────┐
│ Native DLLs (Pull SDK) │
│ - plcommpro.dll (Main SDK) │
│ - pltcpcomm.dll (TCP) │
│ - plrscomm.dll (RS485) │
└─────────────┬───────────────────────────────┘
│ TCP/IP
┌─────────────▼───────────────────────────────┐
│ ZKTeco Fingerprint Device (MVL10) │
└─────────────────────────────────────────────┘
zkteco-java-bridge/
├── dll/ # DLL files location
│ └── *.dll
├── src/
│ └── main/
│ ├── java/com/zkteco/bridge/
│ │ ├── Application.java # Main application
│ │ ├── config/
│ │ │ └── GlobalExceptionHandler.java
│ │ ├── controller/
│ │ │ └── DeviceController.java # REST endpoints
│ │ ├── model/
│ │ │ ├── ApiResponse.java
│ │ │ ├── ConnectRequest.java
│ │ │ ├── UserRequest.java
│ │ │ └── FingerprintRequest.java
│ │ ├── sdk/
│ │ │ └── PullSDK.java # JNA interface
│ │ └── service/
│ │ └── ZKTecoService.java # Business logic
│ └── resources/
│ └── application.properties # Configuration
├── pom.xml # Maven dependencies
└── README.md # This file
Common Pull SDK error codes:
-1- Connection failed / Device not reachable-2- Invalid parameters-3- Command failed-4- Device busy-5- Timeout-6- Insufficient permissions-10- Data not found
This project uses the ZKTeco Pull SDK which is proprietary software. Please ensure you have appropriate licensing from ZKTeco for commercial use.
For issues related to:
- This bridge service: Create an issue in the project repository
- ZKTeco Pull SDK: Contact ZKTeco support at support@zkteco.com
- Device hardware: Contact your device vendor
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
- 1.0.0 (2024-01-20)
- Initial release
- Full CRUD operations for users
- Fingerprint management
- Real-time log monitoring
- Device control functions
- ZKTeco for providing the Pull SDK
- Spring Boot team for the excellent framework
- JNA project for native library access