CEN/XFS作为金融机具开发中举足轻重的标准接口,是广大金融机具开发者都不可避免要深入了解的技术规范,相信初入此行业的同僚们已经阅读过CEN的英文文档,但英文文档比较冗长,且理解上较为困难,故在此摘录其重点知识一二,供大家交流分享;
虽然金融机具受到非现金业务洪流的冲击,已经不是市场的宠儿,但没有过时的技术,只有过时的思想,CEN规范中蕴含的各种技术思想,在程序设计的过程中,仍然是一笔宝贵的财富;
1、开发及运行环境:
CEN原则上仅适用于Windows系列操作系统(Windows2000及更高版本),且官方提供的核心组件XFS Manager仅包含Windows版本,故国内外的设备环境基本都是Windows操作系统;但由于金融机具的安全性及成本考虑,已经有用户及厂商尝试在金融机具上安装Linux系统(如邮储银行),而且发展了一整套和CEN高度相近的规范,由于并非CEN官方提出,故称为类CEN规范,此类规范暂不属于本系列文章之列,将在未来单独开辟专题讨论;
2、CEN/XFS的基础架构:
金融机具(主要为ATM现金机具)的软件部分主要包括应用程序(AP - Application)、中间件程序(SP - Service Provider)、设备驱动程序(Drivers)、维护工具(Maintenance)等,其中,应用程序(以下简称AP)和中间件程序(以下简称SP)位于CEN规范的两端,使得机具厂商只需要开发符合CEN规范的SP,而客户可以选择其他厂商开发符合CEN规范的AP,整个机具的软件系统就可以畅通无阻地运转起来:
AP和SP之间,需要XFS Manager进行中转工作,一般情况下,XFS Manager程序由CEN官方提供,实体文件为三个dll动态链接库“msxfs.dll”、“xfs_conf.dll”、“xfs_supp.dll”,三个库的具体功能将在XFS Manger详解中具体说明,此处仅需要知道三个库提供一系列库函数供AP调用,而SP也会提供dll供XFS Manager调用,也就是说,XFS Manger在AP和SP之间起到了一个“中转站”的作用:
3、异步处理的实现:
CEN规范中,最重要的技术点就是异步处理,CEN通过Windows的消息传递(PostMessage)来实现其异步处理的效果,具体流程为:
a) AP调用XFS Manager动态库提供的异步处理接口函数(WFS系列函数),下发某一指令,指令的输入数据必须使用WFM系列内存管理函数申请内存;
b) XFS Manager调用SP提供的异步处理接口函数(WFP系列函数),传递指令参数;
c) SP在WFP函数中,仅进行数据的拷贝的处理,不进行实际的硬件动作,函数返回WFS_SUCCESS(如果数据拷贝失败则返回相应的错误码);
d) WFP函数返回后,WFS系列函数返回(返回值与WFP函数相同);
e) AP得到WFS函数返回结果,进行其他处理;
f) SP开始对应的硬件动作,硬件动作完成后,组织数据结构体WfsResult(必须使用WFM系列内存管理函数申请内存),包含CEN文档中所要求的“Output”数据,及硬件动作的结果(参见CEN文档附录错误码表及各个指令“Error Code”部分的特殊错误码表);
g) AP接收到Complete类型消息,提取指令返回数据,指令完成,释放WfsResult内存;
以上流程中,红色加粗字体为比较关键的两个步骤,其中步骤e),AP得到了WFS函数的返回结果,但结果只能代码SP接收到了该指令并拷贝了指令数据,并不代表指令执行的结果,AP在此时应该进行“指令传输完成”的判断,进而进行其他操作,并且,这里需要注意,AP后续的操作,如果再涉及该SP程序对应的设备,则在Complete消息返回前,只能在SP程序中“排队”,并不会立即执行,举例说明:AP让存款模块(CIM)进行“钞票计数”,当SP接受指令并开始计数后,可能硬件需要20秒时间进行计数,在此期间,AP如果再下发“打开钞门”指令,则“打开钞门”指令不会立即执行(否则钞票就会想爆米花一样飞出来了),必须要等到“钞票计数”的指令Complete消息发送之后再执行,当然,部分指令之间还会有相互制约的情况,比如你不能直接进行“存款计数”,必须要先执行“开始存款”,这里不一一赘述;
4、同步处理的实现:
除了异步处理外,还有一系列称之为“同步处理”的函数,但实际上,对于SP来说,它们还是进行的异步处理,只是XFS Manager这个强力的“中转站”会等待SP的Complete消息发送后,再将函数返回,从而造成“同步处理”的“假象”,这里不过多描述;需要注意的是,同步处理多适用于获取状态这类的指令,因为在SP方面,获取状态往往仅需要毫秒级的时间,对AP的流程不会有太多影响,而AP则省去了很多处理,提高代码的利用率;
5、单向消息(事件):
除了AP向SP发送指令外,SP程序也可以向AP单方面的发送消息,这类消息被CEN定义为“事件(Event)”,通过SP向已经注册的AP程序窗口抛送消息(PostMessage)实现,关于事件,会有单独的文章进行描述,在此仅需要知道以下几点:
a) 事件是SP单方面发送给AP的,不需要AP进行响应;
b) 事件发送给哪个窗口句柄通过应用调用的注册函数(WFSRegister)“告诉”SP程序;
c) 事件分为4个类型:WFS_SYSTEM_EVENT、WFS_SERVICE_EVENT、WFS_USER_EVENT、WFS_EXECUTE_EVENT;其中WFS_EXECUTE_EVENT比较特殊,它只发送给下发对应指令的AP进程,而其他事件发送给所有注册(WFSRegister)过的进程;
关于事件,可参照如下原文,援引自《CWA 14050-1: 2000》:
There are four classes of events:
• SERVICE_EVENTS
• USER_EVENTS
• SYSTEM_EVENTS
• EXECUTE_EVENTS
For the first three of these event classes, if a class is being monitored and an event occurs in that class, a
message is broadcast to every hWnd registered for that class, specifying the service identified by the hService
handle. The exception to this is the WFS_SYSE_LOCK_REQUESTED system event, this event is posted only
to the application which owns the lock on the device. The events are generated when:
• the service status changes (SERVICE_EVENTS), e.g., a printer is suspended or is no
longer available.
• the service needs an operation from the user to take place (USER_EVENTS), e.g., a
device needs “abnormal” attention, such as adding paper or toner to a printer.
• a system event occurs (SYSTEM_EVENTS), e.g., a hardware error occurs, a version
negotiation fails, the network is no longer available or there is no more disk space.
The EXECUTE_EVENTS class is different from the other three. These are events which occur as a normal part
of processing an WFSExecute command and they are always sent before the completion of the command.
Examples include the need to interact with the user or operator to request an action such as inserting a passbook
into a printer, “swiping” a mag stripe card, etc. A message generated by one of these events is sent only to the
application that issued the WFSExecute that caused the event, even though other applications are registered for
EXECUTE_EVENTS. Note that an application must explicitly register for these events; if it has not, and such
an event occurs, the event is not deliverable and the WFSExecute completes normally.
本章节到此为止,本人技术水平有限,难免有误,欢迎大家指正