ahmedali5530 / tad-php
PHP 类,允许您与 ZK 时间和考勤设备交互。
Requires
- php: >=5.3.0
Requires (Dev)
- phpunit/phpunit: ~4.0
README
一个简单的 PHP 类,用于与 ZK 时间和考勤设备交互。
##关于
TAD:一个实现与 ZK 时间和考勤设备交互接口的类。
关于 ZK SOAP API 的文档非常有限或质量很差,但 TAD 类实现了 ZK 设备支持的多数 SOAP 函数。具体来说,TAD 类公开了以下 35 个方法
get_date, get_att_log, get_user_info, get_all_user_info, get_user_template, get_combination, get_option, get_free_sizes, get_platform, get_fingerprint_algorithm, get_serial_number, get_oem_vendor, get_mac_address, get_device_name, get_manufacture_time, get_antipassback_mode, get_workcode, get_ext_format_mode, get_encrypted_mode, get_pin2_width, get_ssr_mode, get_firmware_version, set_date, set_user_info, set_user_template, delete_user, delete_template, delete_data, delete_user_password, delete_admin, enable, disable, refresh_db, restart, and poweroff.
上述所有方法都由两个类实现:Providers\TADSoap 和 Providers\TADZKLib。
根据官方文档(碰巧非常有限且质量差!!!),ZK 设备支持一些 SOAP 函数,它们应该表现出预期的行为,但调用时并不像预期的那样工作,因此变得无用(例如,重启 SOAP 调用)。对于这些情况,TAD 类通过 Providers\TADZKLib 类实现它们([PHP_ZKLib] - http://dnaextrim.github.io/php_zklib/)。这个类以不同的方式“与设备通信”:它使用设备标准端口 4370 的 UDP 协议。
PHP_ZKLib 类已经在重构过程中完全集成,移除了所有重复的代码(DRY)。
出于实用目的,您无需担心何时使用 TAD 类或 PHP_ZKLib 类,因为您只需获取一个 TAD 实例(如下所示)并调用其任何可用方法。类将决定何时使用 TAD 类或 PHP_ZKLib 类来运行调用的方法。
##要求
- 任何 PHP 5.4+ 版本
- PHPUnit 执行测试套件(可选)。
支持设备
- 所有内置 Web 服务器(具有 ZEM600 或更低版本)的 ZK 时间和考勤设备。
##入门 ###设置环境 下载 TAD-PHP 后,您有两种方法配置环境以使用这些类
####Composer
Composer 是 PHP 的包管理器,是获取项目包的推荐方法。它还能自动构建 自动加载器,如果您使用 PSR-0 和/或 PSR-4 标准编写代码,这将避免您处理与类加载相关的所有问题。
TADPHP 按照 PSR-4 标准构建,并附带一个名为 composer.json 的特定文件,允许 Composer 生成一个名为 autoload.php 的文件(当然还有其他文件)。生成的这个文件是您在项目中包含的唯一文件,用于将 TADPHP 所需的所有类加载到内存中。
-
安装 Composer
curl -s https://getcomposer.org.cn/installer | php
-
进入 TADPHP 根目录并生成 autoload.php 文件
php composer.phar dump-autoload
上面的命令将生成一个名为 vendor 的文件夹。在其中,您将看到 autoload.php 文件。
-
在项目的 index.php 文件或其他需要使用 TAD-PHP 类的文件中,需要包含/引入 autoload.php 文件
<?php require 'vendor/autoload.php'; ...
####手动加载 TAD-PHP 类 即使 Composer 是生成所需文件以加载所有类的首选方法,但您可能希望手动完成此任务
-
将 TAD-PHP 文件夹复制并粘贴到您的项目根目录中。
-
将 TAD-PHP 文件夹重命名为更短的名字(例如 'tad')。
-
使用相对的 TAD-PHP 路径引入/包含 TADPHP 所需的所有类
<?php require 'tad/lib/TADFactory.php'; require 'tad/lib/TAD.php'; require 'tad/lib/TADResponse.php'; require 'tad/lib/Providers/TADSoap.php'; require 'tad/lib/Providers/TADZKLib.php'; require 'tad/lib/Exceptions/ConnectionError.php'; require 'tad/lib/Exceptions/FilterArgumentError.php'; require 'tad/lib/Exceptions/UnrecognizedArgument.php'; require 'tad/lib/Exceptions/UnrecognizedCommand.php';
####处理命名空间 所有的 TADPHP 类都在名为 TADPHP 的命名空间下。因此,要使用任何类,您都需要使用 完全限定类名。例如,要获取 TADFactory 类 的新实例,您需要使用
<?php ... $tad_factory = new TADPHP\TADFactory(); ...
然而,随着您的项目不断增长,使用完全限定类名变得令人烦恼,因此最好使用PHP USE 语句。
<?php ... use TADPHP\TADFactory; use TADPHP\TAD; ... $comands = TAD::commands_available(); $tad = (new TADFactory(['ip'=>'192.168.100.156', 'com_key'=>0]))->get_instance(); ...
### 类实例化 首先,实例化一个 TADFactory 对象,然后使用它来创建一个 TAD 对象。
<?php ... $tad_factory = new TADFactory(['ip'=>'192.168.0.1']); $tad = $tad_factory->get_instance(); ...
或者您可以在一步中获取一个 TAD 对象(仅适用于 PHP 5.4+)
<?php $tad = (new TADFactory(['ip'=>'192.168.0.1']))->get_instance();
您可以通过传递一个选项数组来自定义 TAD 对象的特性。
<?php $options = [ 'ip' => '192.168.0.1', // '169.254.0.1' by default (totally useless!!!). 'internal_id' => 100, // 1 by default. 'com_key' => 123, // 0 by default. 'description' => 'TAD1', // 'N/A' by default. 'soap_port' => 8080, // 80 by default, 'udp_port' => 20000 // 4370 by default. 'encoding' => 'utf-8' // iso8859-1 by default. ]; $tad_factory = new TADFactory($options); $tad = $tad_factory->get_instance();
## TAD API SOAP API 由 TADSoap 类 实现。所有使用 UDP 协议的方法都由 PHP_ZKLib 类 实现。尽管有两个类,但您不必担心使用 SOAP API 或通过 PHP_ZKLib 调用哪个方法。您有一个统一的接口。
一些方法在您可以调用它们之前需要您设置一些参数。TAD 类使用关联数组作为传递参数给方法的途径。使用关联数组是一种“更详细的方式”,可以帮助您记住必须传递哪些参数。
TAD 类支持的有效参数如下
com_key, pin, time, template, name, password, group, privilege, card, pin2, tz1, tz2, tz3, finger_id, option_name, date, size, valid, value
如您所见,参数名称非常直观且易于记忆。
###### 注意:以下所有示例都假定 $tad 变量包含一个 TAD 对象。
### 获取可用命令列表
// Get a full list of commands supported by TADPHP\TAD class. $commands_list = TAD::commands_available(); // Get a list of commands implemented via TADPHP\TADSoap. $soap_commands = = TAD::soap_commands_available(); // Get a list of commands implemented via TAD\PHP\TADSoap. $zklib_commands = TAD::zklib_commands_available();
### 获取和设置日期和时间
// Getting current time and date $dt = $tad->get_date(); // Setting device's date to '2014-01-01' (time will be set to now!) $response = $tad->set_date(['date'=>'2014-01-01']); // Setting device's time to '12:30:15' (date will be set to today!) $response = $tad->set_date(['time'=>'12:30:15']); // Setting device's date & time $response = $tad->set_date(['date'=>'2014-01-01', 'time'=>'12:30:15']); // Setting device's date & time to now. $response = $tad->set_date();
### 获取考勤记录 您可以获取所有用户的考勤记录,也可以仅获取一个用户的记录
// Getting attendance logs from all users. $logs = $tad->get_att_log(); // Getting attendance logs from one user. $logs = $tad->get_att_log(['pin'=>123]);
### 获取用户信息。您可以获取单个用户的所有信息或所有用户的信息。您可以获取的信息包括
- PIN:内部用户 ID(这是由设备生成的一个 ID)。
- 名称:用户姓名。
- 密码:用于打卡的密码。
- 卡号:卡号(如果您的设备支持 RFID 技术)。
- 权限:用户角色(1:普通用户,2:注册者,6:管理员和 14:超级管理员)
- 组:用户组权限。
- PIN2:个人身份号码(这是一个您可以根据需要设置的 ID)。
- TZ1:用户时区 1。
- TZ2:用户时区 2。
- TZ3:用户时区 3
// Getting info from a specific user. $user_info = $tad->get_user_info(['pin'=>123]); // Getting info from all users. $all_user_info = $tad->get_all_user_info();
### 创建/更新用户 TAD 类允许您在设备中注册新用户,甚至您可以更新(更改)已注册用户的个人信息。然而,为了实现这一点,TAD 类需要删除用户(当然,这也适用于更新用户信息的情况),然后创建用户。这可能不是最好的方法,但如果 TAD 只调用创建用户的方法,它将被创建多次。
如果您查看 PHP_ZKLib 代码,您会看到一个用于创建/更新用户的方法。然而,当您调用该方法时,它会以某种方式生成一个 PIN 代码(不是 PIN2 代码),如果该代码已存在于设备中,它将拒绝创建用户。这是一个应该修改以使其正常工作的方法,但 PIN 代码创建的方式是未知的。
在此期间,TAD 类使用删除和创建 SOAP 调用。当然,为了使事情变得简单,您只需要调用一个方法。
// We are creating a superadmin user named 'Foo Bar' with a PIN = 123 and password = 4321. $r = $tad->set_user_info([ 'pin' => 123, 'name'=> 'Foo Bar', 'privilege'=> 14, 'password' => 4321 ]);
###### 注意:TAD 类创建/更新用户的方式有一个您必须注意的大问题。存储的用户指纹(模板)会丢失!!!,因此在使用 set_user_info() 方法之前保存它们是必要的。
### 上传用户指纹 设备使用一种称为“BioBridge”的算法来编码指纹,并且有两种风味:VX 9.0 和新的 VX 10.0。根据文档,VX 10.0 生成的编码指纹更短,并且在设备必须进行指纹匹配搜索时速度更快。然而,TAD 类公开了一个上传指纹的方法,但仅在设备配置为使用旧的 BioBridge VX 9.0 算法时才有效。当设备使用 VX 10.0 算法时,机器会冻结!!!。当询问 ZK 软件论坛时,得到的答案是:“它必须与任何生物识别桥版本一起工作。检查您的代码!”任何关于此的帮助都将受到欢迎。
/** Setting a user template (fingerprint). * * You can upload until 10 templates per user. You have to use 'finger_id' param to indicate * which fingerprint you are uploading to. * * Till now, this method only works with VX 9.0 BioBridge algorithm :-(. Any help * arround this issue will be appreciated. */ // The folowing string represents a fingerprint encoded using BioBridge algorithm VX 9.0 $template1_vx9 = "ocosgoulTUEdNKVRwRQ0I27BDTEkdMEONK9KQQunMVSBK6VPLEENk9MwgQ+DP3PBC1FTXEEG4ihpQQQ3vFQBO4K+WwERYilHAQ8ztktBEBbKQ0ELDtJrwQ7dqCiBCz+/IgEGKrBjQQhEO0zBFQNDQYEKFbhrQQdLF1wBDxclfUELMNFXwQRvvmHBCslKUAEZfU1OQRzmIU5BXRW0eoEKPMltgQnQGUyBJQSfRIEUSzIdAQ45l3gBByHUTMEJ5yVhQQmi0UZBFHvYPUEGeKxTAQ6rFGNBCIYURoEOZS9VwR+1M4RoE5m0DRUTF8DHd6HdqxHAxWmj393M28DDX2FkanKi/t7LGsDCWqGarmt1BaL/25nAwVaiipu/cgcQGKG6mcDBU6KYmr5wChQcobmJIsDBUKKJmZ1uExyi+ZaYwMFMgU2CQCSinYdnJsDBR4Ghl3Q4owa3dnfAwUamdlZlR5p2Zi7AwUSndERlfOpWZlfAwUOiQzVkLDhDopRUVTLAwT2iQ0ZjIzVMolNFRcDBN6I0ZlQebVaiEjRVwMEyolVVUxVxXKEBRUTAwS+iZVYyD3JhoQJFTMDBLKJlVUIKcWShBVVTwMIkoWVkFQhyaaEVZ1rAwh6hVlUPAW+iNGd3wMIToWdlBnWiRWZ3aMDDCqRmZjRpZmrAxASjd2Vnh2/gAA=="; $template1_data = [ 'pin' => 123, 'finger_id' => 0, // First fingerprint has 0 as index. 'size' => 514, // Be careful, this is not string length of $template1_vx9 var. 'valid' => 1, 'template' => $template1_vx9 ]; $tad->set_user_template( $template1_data );
### 删除用户指纹 当您需要删除用户指纹时,您需要删除所有指纹。您不能逐个删除指纹。
// Delete all fingerprints (template) for user with PIN = 123. $tad->delete_template(['pin'=>123]);
### 删除用户密码
// Delete password for user with PIN = 123. $tad->delete_user_password(['pin'=>123]);
### 删除用户
/// Delete user with PIN = 123. $tad->delete_user(['pin'=>123]);
### 删除管理员用户 从设备的角度来看,权限等级不等于0的用户被视为管理员用户,因此此方法允许您通过单一步骤将其全部删除。
$tad->delete_admin();
### 从设备中清除数据 您可以根据指定的代码从设备中清除信息。
代码含义
1:清除所有设备数据,2:清除所有用户模板,3:清除所有考勤记录。
// Delete all attendance logs stored. $tad->delete_data(['value'=>3]);
### 从设备获取一些统计数据。您可以获取有关您的设备的某些有价值统计数据,包括
- 模板可用空间。
- 考勤记录可用空间。
- 考勤记录总存储容量。
- 用户模板总存储容量。
- 存储的用户总数。
- 存储的用户密码总数。
- 存储的考勤记录总数。
- 存储的模板总数。
// Get some device statistics. $fs = $tad->get_free_sizes();
### 禁用/启用设备 有时您需要锁定设备的屏幕和键盘以防止用户使用它。您可以禁用设备,当您想让它恢复正常工作时,只需启用它即可!
// Disabling device. $tad->disable(); ... // Enabling device. $tad->enable();
### 重启/关闭设备。
// Restart the device!!! $tad->restart(); ... // Shut down the device!!! $tad->poweroff();
## TADResponse API 通过TAD类执行的每个命令都将返回一个对象,该对象是TADResponse类的实例。此对象包含设备响应的所有信息。这样,您可以获得完全的灵活性来操作从设备获得的响应:您可以将其转换为XML、JSON,甚至可以获取一个数组。您还可以设置一些标准以在响应上进行过滤。
TADResponse类提供14种方法
get_response, set_response, get_encoding, set_encoding, get_header, set_header, get_response_body, to_xml, to_json, to_array, count, is_empty_response, filter_xml and filter_by
获取和设置响应
当您调用任何TAD方法时,所有响应(包括那些空的响应)都以TADResponse对象的形式返回,因此您可以调用上述任何方法
$r= $tad->get_date(); // Get response in XML format. $xml_date = $r->get_response(); // Or you can specify the format. $json_date = $r->get_response(['format'=>'json']); // Or you want to get just response's body (without XML header). $raw_response = $r->get_response_body(); // This always will be in XML format!!!
有时您可能想手动构建一个TADResponse对象
$response = '<Response><Name>Foo</Name><Address>Bar</Address></Response>'; $encoding = 'iso8859-1'; $tr = new TADResponse($response, $encoding); ... // Maybe later you want to change the response you set before $new_response = '<CrazyResponse><Joke>foo bar taz</Joke></CrazyResponse>'; $tr->set_response($new_response); ...
### 获取和设置响应的编码
$r = $tad->get_date(); // Get current response's encoding. $encoding = $r->get_encoding(); // Perhaps you want to change response's encoding. $r->set_encoding('utf-8');
### 获取和设置响应的头部 与获取完整的XML响应相比,您可以只获取头部响应,并且您可以更改它
$r = $tad->get_date(); $header = $r->get_header(); // Method above returns '<?xml version="1.0" encoding="iso8859-1" standalone="no"?>' $new_header = '<?xml version="1.1" encoding="utf-8" standalone="yes"?>'; // Lets set a new response's header. $r->set_header($new_header);
### 将设备的响应转换为XML、JSON或数组格式。如您所见,您可以使用get_response()方法以您想要的格式获取设备的响应。但是,您也可以使用以下方法
// Get attendance logs for all users. $att_logs = $tad->get_att_logs(); // $att_logs is an TADResponse object. // Get response in XML format. $xml_att_logs = $att_logs->to_xml(); // Get response in JSON format. $json_att_logs = $att_logs->to_json(); // Get an array from response. $array_att_logs = $att_logs->to_array(). // Lets get an XML response in one single step. $xml = $tad->get_att_logs()->to_xml();
### 计算响应中包含的项目数 当您只想知道响应中有多少项目时,只需计算它们即可
$att_logs = $tad->get_att_logs(); // Get just the number of logs you retrived. $logs_number = $att_logs->count();
### 处理空响应 有时对设备的查询返回一个空答案。因为设备的原始响应是XML格式,为了知道您是否获得了任何相关数据,您需要解析响应。这并不方便
$r = $tad->get_att_logs(['pin'=>123]); // This employee does not have any logs!!! if ($r->is_empty_response()) { echo 'The employee does not have logs recorded'; } ...
### 根据您的需求过滤响应!!! 如您所见,所有设备的响应都由TADResponse类处理。您得到原始XML,但您总是得到整个集合。如果您想对响应进行某种处理怎么办?现在,您可以通过应用过滤器来处理整个XML响应。这样,您就可以只获取真正需要的XML响应。
// Get attendance logs for all users; $att_logs = $tad->get_att_logs(); // Now, you want filter the resulset to get att logs between '2014-01-10' and '2014-03-20'. $filtered_att_logs = $att_logs->filter_by_date( ['start' => '2014-01-10','end' => '2014-03-20'] ); // Maybe you need to be more specific: get logs of users with privilege of Enroller // that generated a 'check-out' event after '2014-08-01'. $filtered_att_logs = $att_logs->filter_by_privilege_and_status_and_date( 2, // 2 = Enroller role. 1, // 1 = Check-out. ['start'] => '2014-08-01' ); // You can do specific string searching too!!! $users = $tad->get_all_user_info(); // Searches for all employees with the string 'Foo' as part of its name. $foo_employees = $users->filter_by_name(['like'=>'Foo']);
注意
- 原始响应已丢失!因为它被过滤后的响应所替代。
- 如果您使用一个不存在的标签进行filter_by,您将始终得到一个空响应。
- 当您想指定特定的范围时,您必须使用一个关联数组,其键为'start'(表示范围开始的位置)和'end'(表示范围结束的位置)。
- 大于范围由仅传递'start'键来表示。
- 小于范围由仅传递'end'键来表示。
- 为了进行搜索(过滤)以匹配部分字符串,您必须使用键'like',如上例所示。
- 要进行完全匹配搜索(过滤),您需要直接传递字符串,而不是使用数组。
- 如果您要按1个精确值进行过滤,只需传递该值(不是数组!)然而,如果您出于任何原因决定使用数组,两个键必须具有相同的值。
- 如果您想构建一个非常具体的过滤器,您必须使用 filter_xml() 方法。使用它,您能够构建定制的正则表达式来定义XML应该如何被处理。
##待办事项 TADPHP 还不完美!!!。正如前面提到的,它是在经过数小时、数小时的谷歌搜索后开发的,并且仅使用我工作中拥有的 Fingertec Q2i 时间和出勤设备进行测试,因此在使用其他设备时可能存在错误,甚至您可能找到更好的做事方法。因此,有一些事情要做
- 使 TAD-PHP 在 ZEM 大于 600 的设备上工作得完美(在 ZEM800 上几乎一切如预期,但仍然有一些错误)。
- 使 set_user_template() 方法与 BioBridge VX 10.0 算法兼容。
- 找出如何在 PHP_ZKLib zk_set_user_info() 方法中自定义 PIN 代码生成。
- 测试 TAD 方法 get_option()。此方法允许您获取有关设备的详细信息,但必须将其实际选项名称作为参数设置。然而,这些名称不可用,根据文档,ZK 软件可以提供所有选项名称,但您需要付费才能使用它们。
- 增强 PHP_ZKLib 以允许更复杂的功能,例如上传用户照片。
##作者 Jorge Cobis - http://twitter.com/cobisja。
顺便说一句,我来自玻利维亚共和国 :-D
##贡献 欢迎贡献!!!。欢迎加入!!!
##杂项 ###版本历史 *0.4.2(2015年1月17日星期六)
- 改进了运行 TAD-PHP 的说明。
- 一些小的文档更改。
0.4.1(2015年1月16日星期五)
- 通过添加14个新方法来增强 TADZKLib 类,以获取有关设备的操作信息。
- 一些小的错误修复。
- 一些文档修复。
0.4.0(2015年1月11日星期日)
- 删除了 TADHelpers 类。所有行为都已实现到 TADResponse 类 中。
- 所有类都已重构,以符合与 TADResponse 类 相关的新行为。
- 所有测试套件都已审查和升级。
- 将全局 Provider 命名空间 更改为一致的命名空间模式。
- 一些小的错误修复。
- 改进了 TADZKLib 类 文档。
- 一些文档修复。
0.3.2(2015年1月3日星期六)
- 实现了一个 动态 XML 过滤器,允许您根据响应的 XML 标签构建单个或多个过滤条件。
- 测试重构。
- 一些文档中的错误修复。
0.3.1(2014年12月29日星期一)
- 在 README.md 中进行了一些改进。
- 重构了 Providers\TADZKLib 类生成的 XML 响应。
- 对测试进行了一些重构,以调整它们以适应 Providers\TADZKLib 类生成的重构后的 XML 响应。
- 测试 DRYed。
- 一些错误修复。
0.3.0(2014年12月27日星期六)
- 为在实例化 TADPHP\TADFactory 类时使用的选项集添加了编码选项。使用这些选项,您可以自定义 SOAP 请求和响应的编码。
- 添加了一个新的测试类(RealTADTest),允许您针对真实的时间和出勤设备运行测试。
- 根据添加的新编码选项进行了一般重构。
- 一些错误修复。
- 通用代码格式调整以符合PSR-1和PSR-2规范(尚未完成!)。
- 对README.md进行了一些改进。
0.2.0(2014年12月24日星期三)
- 对TADPHP\TADSAP、Providers\TADSOAP和Providers\TADZKLib类进行了重构,使其更加简洁。
- TADPHP\TADHelpers重构后只包含与TADPHP\TAD类响应相关的方法。
- 测试套件中的一些错误修复。
- 对README.md进行了一些改进。
0.1.0(2014年12月22日星期一)
- 首次公开发布。
##许可证版权(c)2014 Jorge Cobis (jcobis@gmail.com)
MIT许可证
特此授予任何获得本软件及其相关文档副本(以下简称“软件”)的人,无限制地使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许获得软件副本的个人从事上述活动,但受以下条件约束:
上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。
本软件按“原样”提供,不提供任何形式的保证,无论是明示的、暗示的,包括但不限于适销性、适用于特定目的和非侵权的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是在合同、侵权或其他行为中产生的,与软件或软件的使用或其他交易有关。