===== 前言 =====
当前IC卡同步基本都是采用数据库同步方式,除数据库表结构、连接信息外基本遵循相同的逻辑,为减少重复劳动,提升对接效率,研发部完成了IC卡同步标准方案,该方案基于容器实现。
===== 对接步骤 =====
IC卡对接的基本步骤会为:
* 制作SQL脚本
* 配置数据库连接信息
* 获取容器并运行容器
===== 编写SQL脚本 =====
SQL脚本用于查询同步所需要用户,可使用dbeaver/navicat等工具连接到IC卡数据库并在工具中调试,示例为某学校的oracle数据库同步SQL脚本:
SELECT OUTID AS SN,convert(NAME, 'AL32UTF8') as NAME,to_number(SCARDSNR,'xxxxxxxxxx') AS CARD, CUSTDEPT AS dpmno, convert(DPFULLNAME, 'AL32UTF8') AS dpmname, CASE STATUS WHEN 1 THEN 0 ELSE 1 END STATUS FROM M_BASE_CUSTOMERSCARD WHERE STATUS=1 AND CUSTDEPT LIKE '001001%'
通过SQL脚本可以读取到用户的工号、姓名、IC卡号、部门编号、部门名称、卡状态,得到的数据需要满足一些强制要求:
* 必须包含SN/NAME/CARD/DPMNO/DPMNAME/STATUS六列,名称也必须保持一致。——重点说明,必须是大写字母的key,不能是小写。
* 结果必须是UTF8编码,如果数据库编码的不是UTF8需要转码,如示例数据库使用的编码为ZHS16GBK,使用convert转换为utf8编码。
* IC卡号可以接受十进制或十六进制,如果是十六进制卡号需要在卡号前添加'0x'前缀,如0x12345678对应的卡号是305419896。
* STATUS为0表示正常,1表示挂失或失效,如果数据库存储与之不一致,需要使用sql语句处理,如示例数据库中status为1表示正常,因此使用case语句转换为要求值(1转换为0,非1转换为1)。
* 只查询需要的用户,如学生、后勤等不使用设备的人员不要包含在查询结果中,如示例中使用where语句,排除方法可以基于部门名称、部门编号、用户类型等等,具体怎么排除需要同学校协调。
* 工号、姓名、IC卡号为必须的数据,部门名称、部门编号和卡状态如果没有,在SQL语句中设置(NULL)值。
===== 配置数据库 =====
对接对数据库的配置包括新增Mysql同步用户、配置对接数据库基本信息、配置同步时间、配置SQL脚本三项,下图所示为某学校的BaseInfo配置示例。
{{ :idste:ic卡同步baseinfo配置示例.png?400 |}}
=== 修改数据库信息 ===
同步使用iDsteSync用户,该用户仅需要操作BaseInfo和Users表。使用root连接数据库运行如下命令创建新用户并授权:
在nccs数据库中执行如下命令用于修改、创建表和数据:
* ALTER TABLE `nccs`.`BaseInfo` CHANGE COLUMN `Description` `Description` VARCHAR(1024) NULL DEFAULT NULL ;
* grant select,update,delete,insert on nccs.BaseInfo to 'iDsteSync'@'127.0.0.1' identified by 'iDste1057Sync';
* grant select,insert,delete,update,drop on nccs.Timetable to 'iDsteSync'@'127.0.0.1';
* grant select,insert,delete,update on nccs.Users to 'iDsteSync'@'127.0.0.1';
* grant select on nccs.SectionTable to 'iDsteSync'@'127.0.0.1';
* grant insert on nccs.SystemLog to 'iDsteSync'@'127.0.0.1';
* grant select on nccs.DeviceList to 'iDsteSync'@'127.0.0.1';
* grant select,update,delete,insert on nccs.Users to 'iDsteSync'@'127.0.0.1';
* flush privileges;
R07.04以上的服务器版本还需要执行以下sql语句给iDsteSync用户OAuthAppInfo表的查询权限:
* grant select on nccs.OAuthAppInfo to 'iDsteSync'@'127.0.0.1';
* flush privileges;
===== 配置对接数据库基本信息 =====
BaseInfo表中的302-307的Descrption配置了连接IC卡数据库所需基本信息,定义如下:
* 302 IC卡数据库IP
* 303 IC卡数据库库名
* 304 IC卡数据库用户名
* 305 IC卡数据库密码
* 306 IC卡数据库类型,可选为oracle/service表示基于oracle的service name连接;oracle/sid表示基于oracle的sid连接;sqlsrv为mssql service数据库
* 307 IC卡数据库端口
===== 配置同步时间 =====
BaseInfo.301.Description配置IC卡同步时间点,24小时制,整点同步,多个同步时间以逗号分隔,示例
* BaseInfo.301.Description=6,8,10,12 表示每天6、8、10、12点各同步一次共同步4次。
===== ORACLE配置环境变量 =====
BaseInfo.298.Descrption为数据库环境变量,,不填时使用NLS_LANG=AMERICAN_AMERICA.UTF8,如果默认配置不能得到正常编码,还可以尝试NLS_LANG=AMERICAN_AMERICA.ZHS16GBK;此配置在对接ORACLE数据库时非常重要,否则会导致导入的用户姓名乱码。
===== 用户默认权限 =====
BaseInfo.3001.Description未配置或配置为1时表示默认授权所有设备的使用权限,为0表示默认不授权。
=== 配置SQL脚本 ===
BaseInfo表中ID为[10100,10199]的Description配置项保留为SQL脚本配置,每一行为一个SQL语句,最多1024字节
===== 运行容器 =====
* 服务器R07.02及以上版本:使用名字为idste.ic.sync.r7.2的容器。
* 服务器R06.08及以下版本:使用名字为idste.ic.sync.r6.8的容器。
docker软件安装参考[[DOCKER容器安装]],镜像存储在ccr.ccs.tencentyun.com/idste-cus/idste.ic.sync.r6.8:latest,使用方法:
* docker login --username 100008766382 ccr.ccs.tencentyun.com # 密码为iDste1057Hello(该账户如有变更,请联系公司腾讯云管理人员处理)
* docker pull ccr.ccs.tencentyun.com/idste-cus/idste.ic.sync.r6.8
* docker run -itd --name idste.ic.sync --net=host --restart=always ccr.ccs.tencentyun.com/idste-cus/idste.ic.sync.r6.8 # 运行容器,--restart=always表示容器退出后自动重启, --net=host使用主机网络
* docker logout ccr.ccs.tencentyun.com # 退出镜像服务器
===== 结果检查 =====
容器运行后可使用docker logs -f idste.ic.sync,在容器运行60秒开始同步并能在屏幕上看到一些信息,如果看到报错,请检查数据库连接、sql脚本等。
===== 运行日志 =====
容器运行时会向容器中的/var/log/workerman/icsync.log写入日志,查看方法:
* docker exec -it idste.ic.sync /bin/bash
* cat /var/log/workerman/icsync.log
* exit 退出容器
正常情况应该能看到同步失败的用户卡号和同步成功的用户数等日志信息。
====== 修订日志 ======
2019-09-06 增加同步日志,同步成功后添加系统日志,内容形如"IC卡同步成功,同步[xxx]条"。如果R6.2及以下版本需要有如下更改:
1. vi /home/www/api/common/messages/zh-CN/message.php
return [
......之后添加以下内容.......
'type/server' => "服务器",
'title/server/ic-sync' => "IC卡同步成功,同步「{title1}」条",
'title/server/timetable-sync' => "课表同步成功,同步「{title1}」条",
];
2. vi /home/www/api/api/controllers/BaseController.php
public $logActions = [
......之后添加以下内容.......
'server' => ['ic_sync', 'timetable_sync']
];