Compare commits
16 Commits
master
...
563bc271f3
| Author | SHA1 | Date | |
|---|---|---|---|
| 563bc271f3 | |||
| 787892924b | |||
| 40b26f94d8 | |||
| aec28f662a | |||
| fd2baf7d33 | |||
| 478d88f3c4 | |||
| 63a9070f56 | |||
| 5a84be620d | |||
| ed61a25ac4 | |||
| fc1e02264d | |||
| f966dd9387 | |||
| 117f293e83 | |||
| 0ebf6d4258 | |||
| 9f3596abd6 | |||
| 52abbf6a8f | |||
| 0fdb14af2a |
113
pom.xml
113
pom.xml
@@ -4,10 +4,11 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.dpkj</groupId>
|
||||
<artifactId>银医通-澜沧中医院-DLL-台式机</artifactId>
|
||||
<!-- 银医通-澜沧中医院-DLL-台式机 -->
|
||||
<artifactId>yinyitong-dll-stand</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>ems-express-call-dll</name>
|
||||
<description>ems-express-call-dll</description>
|
||||
<name>yinyitong-dll-stand</name>
|
||||
<description>银医通-澜沧中医院-DLL-台式机</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -34,11 +35,13 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@@ -50,12 +53,14 @@
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 调用DLL -->
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>${jna.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
@@ -68,15 +73,115 @@
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>${pdfbox.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- json处理-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.83</version>
|
||||
</dependency>
|
||||
|
||||
<!-- thymeleaf-->
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-spring5</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Flying Saucer for HTML to Image 把html转换为图片 -->
|
||||
<dependency>
|
||||
<groupId>org.xhtmlrenderer</groupId>
|
||||
<artifactId>flying-saucer-core</artifactId>
|
||||
<version>9.1.22</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ZXing for QR Code 二维码生成-->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSoup HTML Parser -->
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.15.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ognl</groupId>
|
||||
<artifactId>ognl</artifactId>
|
||||
<version>3.1.28</version> <!-- 可以根据实际情况调整版本 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.15</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>ems-express-call-dll</finalName>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<!-- 跳过单元测试 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
|
||||
|
||||
<!-- 不需要分开打包的就将下面的插件全部注释-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-dependency-plugin</artifactId>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <id>copy-dependencies</id>-->
|
||||
<!-- <phase>prepare-package</phase>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>copy-dependencies</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <!– 拷贝项目依赖包到lib/目录下 –>-->
|
||||
<!-- <outputDirectory>${project.build.directory}/lib</outputDirectory>-->
|
||||
<!-- <overWriteReleases>false</overWriteReleases>-->
|
||||
<!-- <overWriteSnapshots>false</overWriteSnapshots>-->
|
||||
<!-- <overWriteIfNewer>true</overWriteIfNewer>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <layout>ZIP</layout>-->
|
||||
<!-- <includes>-->
|
||||
<!-- <include>-->
|
||||
<!-- <groupId>nothing</groupId>-->
|
||||
<!-- <artifactId>nothing</artifactId>-->
|
||||
<!-- </include>-->
|
||||
<!-- </includes>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
|
||||
|
||||
</plugins>
|
||||
<!--打包时将resource下的文件一起打包-->
|
||||
<resources>
|
||||
|
||||
37
src/main/java/com/dpkj/common/config/MvcConfig.java
Normal file
37
src/main/java/com/dpkj/common/config/MvcConfig.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.dpkj.common.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
|
||||
/**
|
||||
* mvcConfig配置类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2023-05-23 15:24:43
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Configuration
|
||||
public class MvcConfig extends WebMvcConfigurationSupport {
|
||||
|
||||
/**
|
||||
* 添加资源过滤处理器
|
||||
* @param registry 资源处理器
|
||||
*/
|
||||
@Override
|
||||
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/**")
|
||||
.addResourceLocations("classpath:/static/");
|
||||
registry.addResourceHandler("/swagger-ui.html/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
registry.addResourceHandler("/swagger-ui/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
|
||||
.resourceChain(false);
|
||||
|
||||
super.addResourceHandlers(registry);
|
||||
}
|
||||
|
||||
}
|
||||
27
src/main/java/com/dpkj/common/constant/LexMarkConst.java
Normal file
27
src/main/java/com/dpkj/common/constant/LexMarkConst.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.dpkj.common.constant;
|
||||
|
||||
/**
|
||||
* 利盟台式机 设备调用逻辑名
|
||||
*/
|
||||
public interface LexMarkConst {
|
||||
/**
|
||||
* 身份证读取
|
||||
*/
|
||||
String ID_CARD_READ = "RFIDCardReader";
|
||||
/**
|
||||
* 社保卡读取
|
||||
*/
|
||||
String CARD_READER = "CardReader";
|
||||
/**
|
||||
* 打印机
|
||||
*/
|
||||
String RECEIPT_PRINTER = "ReceiptPrinter";
|
||||
/**
|
||||
* 数字键盘
|
||||
*/
|
||||
String ENCRYPTOR = "Encryptor";
|
||||
/**
|
||||
* 扫描仪
|
||||
*/
|
||||
String BARCODE_READER = "BarcodeReader";
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.dpkj.common.constant;
|
||||
|
||||
/**
|
||||
* 利盟台式机 中间件 方法名常量
|
||||
*/
|
||||
public interface MiddlewareFunctionsConst {
|
||||
|
||||
/**-------------------- 公共模块 ---------------------*/
|
||||
/**
|
||||
* 打开设备(异步)/ (同步)
|
||||
*/
|
||||
String OPEN_CONNECTION = "OpenConnection";
|
||||
String OPEN_CONNECTION_SYNC = "OpenConnectionSync";
|
||||
|
||||
/**
|
||||
* 关闭设备(异步)/ (同步)
|
||||
*/
|
||||
String CLOSE_CONNECTION = "CloseConnection";
|
||||
String CLOSE_CONNECTION_SYNC = "CloseConnectionSync";
|
||||
|
||||
|
||||
/** ------------------- 读卡模块 --------------------*/
|
||||
/**
|
||||
* 进卡读卡(异步)/ (同步)
|
||||
*/
|
||||
String ACCEPT_AND_READ_TRACKS = "AcceptAndReadTracks";
|
||||
String ACCEPT_AND_READ_TRACKS_SYNC = "AcceptAndReadTracksSync";
|
||||
|
||||
/**
|
||||
* 同步取消进卡
|
||||
*/
|
||||
String CANCEL_ACCEPT = "CancelAccept";
|
||||
|
||||
/**
|
||||
* 异步Chip(IC卡片)数据交互 / 同步Chip(IC卡片)数据交互
|
||||
*/
|
||||
String CHIP_IO = "ChipIo";
|
||||
String CHIP_IO_SYNC = "ChipIoSync";
|
||||
|
||||
/**
|
||||
* IC卡上电
|
||||
*/
|
||||
String CHIPPOWER = "ChipPower";
|
||||
|
||||
/**
|
||||
* 退卡
|
||||
*/
|
||||
String EJECT = "Eject";
|
||||
|
||||
/**
|
||||
* 获取属性
|
||||
*/
|
||||
String GET_CAPABILITIES = "GetCapabilities";
|
||||
|
||||
/**
|
||||
* 获取状态 同步/异步
|
||||
*/
|
||||
String GET_STATUS = "GetStatus";
|
||||
String GET_STATUS_SYNC = "GetStatusSync";
|
||||
|
||||
/**
|
||||
* 社保卡读取 读基本信息
|
||||
*/
|
||||
String I_READ_CARD_BAS = "iReadCardBas";
|
||||
|
||||
/**
|
||||
* 社保卡读取 基于加密机的读基本信息
|
||||
*/
|
||||
String I_READ_CARD_BAS_HSM_STEP1 = "iReadCardBas_HSM_Step1";
|
||||
|
||||
/**
|
||||
* 社保卡读取 基于加密机的读基本信息
|
||||
*/
|
||||
String I_READ_CARD_BAS_HSM_STEP2 = "iReadCardBas_HSM_Step2";
|
||||
|
||||
|
||||
/** -------------------- 数字键盘模块 -----------------*/
|
||||
/**
|
||||
* 明文输入
|
||||
*/
|
||||
String INPUT_DATA = "InputData";
|
||||
|
||||
/**
|
||||
* 密文输入
|
||||
*/
|
||||
String INPUT_PIN = "InputPIN";
|
||||
|
||||
/**
|
||||
* 取消输入 (明文或者密文)
|
||||
*/
|
||||
String CANCEL_INPUT = "CancelInput";
|
||||
|
||||
/** ------------------ 条码读取模块 -------------------*/
|
||||
/**
|
||||
* 复位扫描仪
|
||||
*/
|
||||
String RESET = "Reset";
|
||||
|
||||
/**
|
||||
* 扫描条码
|
||||
*/
|
||||
String SCAN_BARCODE = "ScanBarcode";
|
||||
|
||||
/**
|
||||
* 取消扫描
|
||||
*/
|
||||
String CANCEL_SCAN = "CancelScan";
|
||||
|
||||
/**
|
||||
* 获取扫描仪状态
|
||||
*/
|
||||
String GET_SCANNER_STATUS = "GetStatus";
|
||||
|
||||
/**
|
||||
* 获取能力
|
||||
*/
|
||||
String GET_SCANNER_CAPABILITIES = "GetCapabilities";
|
||||
|
||||
}
|
||||
63
src/main/java/com/dpkj/common/dto/LexMarkDTO.java
Normal file
63
src/main/java/com/dpkj/common/dto/LexMarkDTO.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package com.dpkj.common.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 利盟请求参数DTO
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:46:44
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LexMarkDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 默认异步
|
||||
* 0:代表同步,1:代表异步,3:代表属性
|
||||
*/
|
||||
private Integer methodType = 1;
|
||||
|
||||
/**
|
||||
* 默认:com.gwi.device
|
||||
* 插件名称:如果是设备调用,则固定填写com.gwi.device;如果是插件调用,此处填
|
||||
* 写插件动态库文件名(去掉文件名前面的lib和文件后缀名,如:GWI_Plugin)
|
||||
*/
|
||||
private String pluginName = "com.gwi.device";
|
||||
|
||||
/**
|
||||
* 固定填写execute
|
||||
*/
|
||||
private String pluginMethod = "execute";
|
||||
|
||||
/**
|
||||
* 设备名。如果是设备调用,则填写设备名称,需要和SP服务配置中的 DevList.ini 配置的设备名称一致;
|
||||
* 如果是插件调用,可忽略此参数
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 调用id,应用生成,用于区分不同的调用
|
||||
*/
|
||||
private Integer callID;
|
||||
|
||||
/**
|
||||
* 调用的函数名称,设备执行的动作名称,简称动作名
|
||||
*/
|
||||
private String actionName;
|
||||
|
||||
/**
|
||||
* 设备执行的输入参数,格式为json字符串(注意,此处为字符串,不是json对象)
|
||||
*/
|
||||
private String param;
|
||||
|
||||
}
|
||||
|
||||
115
src/main/java/com/dpkj/common/dto/LexMarkResultDTO.java
Normal file
115
src/main/java/com/dpkj/common/dto/LexMarkResultDTO.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.dpkj.common.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 利盟接口返回值DTO
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 11:03:06
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LexMarkResultDTO <T> implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String msgName;
|
||||
|
||||
/**
|
||||
* 对应发送请求的callID。
|
||||
*/
|
||||
private int callID;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 发送请求中的actionName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
/**
|
||||
* 利盟服务返回的参数
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String param;
|
||||
|
||||
/**
|
||||
* 实际返回的接受的参数对象(通过param转换过后的)
|
||||
*/
|
||||
private T data;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Param {
|
||||
|
||||
/**
|
||||
* 请求ID
|
||||
*/
|
||||
private int RequestID;
|
||||
|
||||
/**
|
||||
* 命令编码
|
||||
*/
|
||||
private int dwCommandCode;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String eventName;
|
||||
|
||||
/**
|
||||
* 事件类型编码
|
||||
*/
|
||||
private int eventType;
|
||||
|
||||
/**
|
||||
* 服务
|
||||
*/
|
||||
private int hService;
|
||||
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
58
src/main/java/com/dpkj/common/dto/LexMarkResultVO.java
Normal file
58
src/main/java/com/dpkj/common/dto/LexMarkResultVO.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.dpkj.common.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 利盟接口返回值DTO
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 11:03:06
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LexMarkResultVO<T> implements Serializable {
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String msgName;
|
||||
|
||||
/**
|
||||
* 对应发送请求的callID。
|
||||
*/
|
||||
private int callID;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 发送请求中的actionName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 返回参数
|
||||
*/
|
||||
private T param;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
}
|
||||
|
||||
139
src/main/java/com/dpkj/common/exception/ControllerAdvice.java
Normal file
139
src/main/java/com/dpkj/common/exception/ControllerAdvice.java
Normal file
@@ -0,0 +1,139 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* controller控制器异常处理接口实现类
|
||||
* <p>其它module可以集成此类进行controller层的异常处理</p>
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RestControllerAdvice(annotations = {RestController.class, Controller.class})
|
||||
public class ControllerAdvice {
|
||||
|
||||
/**
|
||||
* controller方法中的参数校验失败,但是前提是要使用
|
||||
* #@Validated注解开启参数校验
|
||||
*
|
||||
* @param e 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = MethodArgumentNotValidException.class)
|
||||
public Result<String> bindingException(MethodArgumentNotValidException e) {
|
||||
// 获得所有校验出错的返回集
|
||||
BindingResult bindingResult = e.getBindingResult();
|
||||
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
|
||||
// 循环获得所有校验异常的字段
|
||||
Map<String, String> fieldMap = new HashMap<>();
|
||||
for (FieldError fieldError : fieldErrors) {
|
||||
fieldMap.put(fieldError.getField(), fieldError.getDefaultMessage());
|
||||
}
|
||||
|
||||
String errMsg = fieldMap.values().toString().replaceAll("]", "").replaceAll("\\[", "");
|
||||
log.warn(errMsg);
|
||||
// 返回给前端
|
||||
return Result.error(errMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理空指针异常
|
||||
* @param nullPointerException 空指针异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = NullPointerException.class)
|
||||
public Result<String> nullPointException(NullPointerException nullPointerException) {
|
||||
log.error("空指针异常类型: {},信息: {}", nullPointerException.getClass(),nullPointerException.getMessage());
|
||||
return Result.error(ErrorEnum.NULL_POINTER_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有的运行时异常,抛出异常
|
||||
* @param throwable 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = Throwable.class)
|
||||
public Result<String> handleException(Throwable throwable) {
|
||||
log.error("异常类型: {}, {}, 信息为: {}", throwable.getCause(), throwable.getClass(), throwable.getMessage());
|
||||
if (throwable instanceof RRException){
|
||||
RRException rrException = (RRException) throwable;
|
||||
return Result.error(rrException.getCode(), rrException.getMsg());
|
||||
}
|
||||
return Result.error(ErrorEnum.RUNTIME_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* http信息无可读
|
||||
* @param e 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = HttpMessageNotReadableException.class)
|
||||
public Result<String> httpMessageNotReadAbleException(HttpMessageNotReadableException e){
|
||||
log.warn("异常类型: {} 无可读信息: {}", e.getClass(), e.getMessage());
|
||||
return Result.error(ErrorEnum.HTTP_MESSAGE_NOT_READABLE_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行时异常
|
||||
* @param e 运行异常对象
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = RuntimeException.class)
|
||||
public Result<String> runtimeException(RuntimeException e){
|
||||
log.error("运行时异常:{}", e.getMessage());
|
||||
if (e instanceof RRException){
|
||||
RRException rrException = (RRException) e;
|
||||
return Result.error(rrException.getCode(), rrException.getMsg());
|
||||
}
|
||||
return Result.error(ErrorEnum.RUNTIME_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求不支持
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
|
||||
public Result<String> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
|
||||
log.warn("暂不支持该请求: {}", e.getMessage());
|
||||
return Result.error("暂不支持此请求方式");
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数类型错误
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public Result<String> methodArgument(MethodArgumentTypeMismatchException e){
|
||||
log.warn("参数发生错误: {}", e.getMessage());
|
||||
return Result.error("参数发生错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 缺少请求参数
|
||||
* @param e 缺少请求参数异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
public Result<String> exception(MissingServletRequestParameterException e){
|
||||
log.warn("缺少请求参数: {}", e.getMessage());
|
||||
return Result.error("缺少请求参数");
|
||||
}
|
||||
|
||||
}
|
||||
70
src/main/java/com/dpkj/common/exception/ErrorEnum.java
Normal file
70
src/main/java/com/dpkj/common/exception/ErrorEnum.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/**
|
||||
* 错误返回枚举类
|
||||
*/
|
||||
@Getter
|
||||
public enum ErrorEnum implements ErrorInterface{
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
* 成功范围
|
||||
* @code 200
|
||||
* @apiNote 访问成功
|
||||
*/
|
||||
SUCCESS(200, "访问成功"),
|
||||
|
||||
/**
|
||||
* 系统异常
|
||||
* @code 500
|
||||
* @apiNote 系统异常
|
||||
*/
|
||||
FAIL(500, "系统异常"),
|
||||
|
||||
/**
|
||||
* 调用对象位空(null)
|
||||
* @code 10002
|
||||
* @apiNote 调用对象位空(null)
|
||||
*/
|
||||
NULL_POINTER_EXCEPTION(501, "调用对象位空(null)"),
|
||||
|
||||
/**
|
||||
* 运行时异常,
|
||||
* @code 10003
|
||||
* @apiNote 系统发生错误,请联系管理员
|
||||
*/
|
||||
RUNTIME_EXCEPTION(502, "系统发生错误,请联系管理员"),
|
||||
|
||||
/**
|
||||
* Http传入的参数没有可以读的数据
|
||||
* @code 10004
|
||||
* @apiNote 传入的数据不可读
|
||||
*/
|
||||
HTTP_MESSAGE_NOT_READABLE_EXCEPTION(503, "传入的数据不可读"),
|
||||
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
;
|
||||
private final Integer code;
|
||||
private final String message;
|
||||
ErrorEnum(Integer code, String message){
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCode(){
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage(){
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
23
src/main/java/com/dpkj/common/exception/ErrorInterface.java
Normal file
23
src/main/java/com/dpkj/common/exception/ErrorInterface.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
/**
|
||||
* 错误枚举接口,所有的错误枚举都需要实现该接口,如果需要自定义
|
||||
* 错误信息,可通过实现该接口与RespBean进行使用
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @see com.dpkj.common.vo.Result
|
||||
* @since 2023-07-27 13:05:00
|
||||
*/
|
||||
public interface ErrorInterface {
|
||||
|
||||
/**
|
||||
* 获取响应码
|
||||
*/
|
||||
int getCode();
|
||||
|
||||
/**
|
||||
* 获取响应信息
|
||||
*/
|
||||
String getMessage();
|
||||
|
||||
}
|
||||
59
src/main/java/com/dpkj/common/exception/RRException.java
Normal file
59
src/main/java/com/dpkj/common/exception/RRException.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 总的异常,所有的自定义异常都需要继承类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2023-07-24 09:42:00
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class RRException extends RuntimeException{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String msg;
|
||||
private int code = 500;
|
||||
|
||||
public RRException(){
|
||||
super("系统错误");
|
||||
this.msg = "系统错误";
|
||||
}
|
||||
|
||||
public RRException(Throwable throwable){
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public RRException(String msg) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(int code, String msg) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
public RRException(ErrorInterface error){
|
||||
super(error.getMessage());
|
||||
this.code = error.getCode();
|
||||
this.msg = error.getMessage();
|
||||
}
|
||||
|
||||
public RRException(int code,String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
336
src/main/java/com/dpkj/common/utils/TemplateUtils.java
Normal file
336
src/main/java/com/dpkj/common/utils/TemplateUtils.java
Normal file
@@ -0,0 +1,336 @@
|
||||
package com.dpkj.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
|
||||
import org.thymeleaf.templatemode.TemplateMode;
|
||||
import org.thymeleaf.templateresolver.StringTemplateResolver;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xhtmlrenderer.layout.SharedContext;
|
||||
import org.xhtmlrenderer.simple.Graphics2DRenderer;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 模板服务类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-01-18 15:33:51
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class TemplateUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 生成小票图片
|
||||
*
|
||||
* @param data json数据,用来填充模板
|
||||
* @param template 模板(html字符串或者模板名称)
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @param saveDir 图片的保存路径,如果为空,那么不进行图片的保存
|
||||
* @return 图片字节数组
|
||||
*/
|
||||
public byte[] generateReceiptImage(JSONObject data, String template, int width, int height, StringBuilder saveDir) {
|
||||
try {
|
||||
// 获取模板上下文
|
||||
Context context = this.getContext(data);
|
||||
|
||||
TemplateEngine templateEngine = new TemplateEngine();
|
||||
if (checkIsHtml(template)) {
|
||||
StringTemplateResolver resolver = new StringTemplateResolver();
|
||||
resolver.setTemplateMode("HTML");
|
||||
// 设置模板引擎使用这个自定义的模板解析器
|
||||
templateEngine.setTemplateResolver(resolver);
|
||||
}else {
|
||||
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
|
||||
resolver.setPrefix("classpath:/templates/");
|
||||
resolver.setSuffix(".html");
|
||||
resolver.setTemplateMode(TemplateMode.HTML);
|
||||
resolver.setCacheable(true);
|
||||
resolver.setApplicationContext(new AnnotationConfigReactiveWebApplicationContext());
|
||||
templateEngine.setTemplateResolver(resolver);
|
||||
}
|
||||
|
||||
// 渲染模板
|
||||
String html = templateEngine.process(template, context);
|
||||
|
||||
BufferedImage image = this.generate(html, width, height);
|
||||
|
||||
// 保存图片
|
||||
if (saveDir != null && !"".equals(saveDir.toString())) {
|
||||
String outputPath = saveDir.toString() + "\\genera_image_" + System.currentTimeMillis() + ".png";
|
||||
ImageIO.write(image, "PNG", new File(outputPath));
|
||||
saveDir.reverse();
|
||||
saveDir.append(outputPath);
|
||||
}
|
||||
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "PNG", byteOutputStream);
|
||||
return byteOutputStream.toByteArray();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RRException("图片打印失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成图片
|
||||
* @param html html内容
|
||||
*/
|
||||
private BufferedImage generate(String html, int width, int height){
|
||||
try {
|
||||
// 转换为xhtml
|
||||
String xhtml = this.htmlToXhtml(html);
|
||||
|
||||
// 转换为document
|
||||
Document document = this.xhtmlToDocument(xhtml);
|
||||
|
||||
// 生成图片
|
||||
return createImageToDocument(document, width, height);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RRException("图片打印失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过JsonObject进行context内容填充
|
||||
* @param data jsonObject
|
||||
* @return context
|
||||
*/
|
||||
private Context getContext(JSONObject data) {
|
||||
// 创建Thymeleaf上下文
|
||||
Context context = new Context();
|
||||
if ( data != null) {
|
||||
Set<String> keys = data.keySet();
|
||||
for (String key : keys) {
|
||||
// 判单是否有图片生成,统一后面采用的是_2base64Type
|
||||
String[] split = key.split("_");
|
||||
if (split.length > 1 && split[1].equals("2base64Type")) {
|
||||
int width = split.length > 2 ? Integer.parseInt(split[2]) : 100;
|
||||
int height = split.length > 3 ? Integer.parseInt(split[3]) : 100;
|
||||
// 如果是图片类型,需要进行base64转换
|
||||
String base64 = this.generateQRCode(String.valueOf(data.get(key)), width, height);
|
||||
context.setVariable(split[0], "data:image/jpeg;base64," + base64);
|
||||
} else {
|
||||
// 普通字段直接设置
|
||||
context.setVariable(key, data.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据内容生成二维码
|
||||
* @param content 转换内容
|
||||
*/
|
||||
private String generateQRCode(String content, int width, int height) {
|
||||
try {
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 设置字符编码为 UTF-8
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 设置纠错级别
|
||||
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
|
||||
BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
qrImage.createGraphics();
|
||||
|
||||
Graphics2D graphics = (Graphics2D) qrImage.getGraphics();
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, width, height);
|
||||
graphics.setColor(Color.BLACK);
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
if (bitMatrix.get(i, j)) {
|
||||
graphics.fillRect(i, j, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(qrImage, "png", baos);
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
}catch (Exception e){
|
||||
log.error("二维码生成失败");
|
||||
throw new RRException("二维码生成失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xhtml 转换为 Document
|
||||
* @param xhtml xhtml
|
||||
* @return document
|
||||
* @throws Exception e
|
||||
*/
|
||||
private Document xhtmlToDocument(String xhtml) throws Exception {
|
||||
// 创建DocumentBuilder
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setValidating(false);
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
|
||||
// 解析XHTML字符串为Document
|
||||
return builder.parse(new ByteArrayInputStream(xhtml.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换,将html转换为xhtml
|
||||
* @param html html内容
|
||||
* @return xhtml
|
||||
*/
|
||||
private String htmlToXhtml(String html) {
|
||||
org.jsoup.nodes.Document doc = Jsoup.parse(html);
|
||||
doc.outputSettings()
|
||||
.syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml)
|
||||
.charset(StandardCharsets.UTF_8);
|
||||
|
||||
// 不使用外部DTD
|
||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
|
||||
"<head>\n" +
|
||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n" +
|
||||
"<style type=\"text/css\">\n" +
|
||||
"body { font-family: SimSun, serif; }\n" +
|
||||
"</style>\n" +
|
||||
"</head>\n" +
|
||||
"<body>\n" +
|
||||
doc.body().html() +
|
||||
"\n</body>\n" +
|
||||
"</html>";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过document转换为图片
|
||||
* @param document doc
|
||||
* @param width 图片的宽度
|
||||
* @param height 图片的高度
|
||||
* @return bufferedImage
|
||||
*/
|
||||
private BufferedImage createImageToDocument(Document document, int width, int height) {
|
||||
try {
|
||||
// 创建Dimension对象
|
||||
Dimension dimension = new Dimension(width, height);
|
||||
|
||||
// 创建图片
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D graphics = (Graphics2D) image.getGraphics();
|
||||
|
||||
// 设置白色背景
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, width, height);
|
||||
|
||||
// 设置渲染提示
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
// 创建渲染器
|
||||
Graphics2DRenderer renderer = new Graphics2DRenderer();
|
||||
renderer.setDocument(document, null);
|
||||
|
||||
// 设置渲染参数
|
||||
SharedContext sharedContext = renderer.getSharedContext();
|
||||
sharedContext.setInteractive(false);
|
||||
sharedContext.setDPI(256f);
|
||||
|
||||
// 使用系统默认字体,假设系统默认字体支持UTF - 8
|
||||
Font font = new Font(Font.DIALOG, Font.PLAIN, 20);
|
||||
graphics.setFont(font);
|
||||
|
||||
// 使用Dimension对象进行布局
|
||||
renderer.layout(graphics, dimension);
|
||||
renderer.render(graphics);
|
||||
|
||||
graphics.dispose();
|
||||
return image;
|
||||
} catch (Exception e) {
|
||||
throw new RRException("渲染图片失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验这个模板内容是不是html字符串,而非模板名称
|
||||
* @param template template
|
||||
* @return 是否是html字符串
|
||||
*/
|
||||
private boolean checkIsHtml(String template){
|
||||
try {
|
||||
String pattern = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>";
|
||||
Pattern r = Pattern.compile(pattern);
|
||||
return r.matcher(template).find();
|
||||
}catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将document对象转换为字符串
|
||||
* @param doc document
|
||||
* @return document转换为的字符串
|
||||
*/
|
||||
private String documentToString(Document doc) {
|
||||
try {
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Transformer transformer = tf.newTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
transformer.transform(new DOMSource(doc), new StreamResult(writer));
|
||||
return writer.getBuffer().toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
114
src/main/java/com/dpkj/common/utils/ThirdService.java
Normal file
114
src/main/java/com/dpkj/common/utils/ThirdService.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package com.dpkj.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thymeleaf.util.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
/**
|
||||
* 第三方服务,主要是调用打印机等
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:45:01
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ThirdService {
|
||||
|
||||
@Value("${app.custom.lexMarkServiceIp}")
|
||||
private String lexMarkServiceIp;
|
||||
@Value("${app.custom.lexMarkServicePort}")
|
||||
private String lexMarkServicePort;
|
||||
|
||||
/**
|
||||
* 利盟台式机-立体机 接口请求
|
||||
*
|
||||
* @param lexMarkDTO 请求DTO
|
||||
* @return result
|
||||
*/
|
||||
public <T> LexMarkResultDTO<T> callDevice(LexMarkDTO lexMarkDTO, Class<T> clazz) {
|
||||
try {
|
||||
URL url = new URL(lexMarkServiceIp + ":" + lexMarkServicePort + "/CallDevice");
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
|
||||
// 将LexMarkDTO对象转换为JSON字符串
|
||||
String jsonInputString = JSON.toJSONString(lexMarkDTO);
|
||||
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
|
||||
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
|
||||
wr.write(input, 0, input.length);
|
||||
log.info(jsonInputString);
|
||||
}
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||
log.error("利盟服务请求失败,响应码:{},请求参数:{}", responseCode, lexMarkDTO);
|
||||
throw new RRException("利盟服务请求失败,响应码:" + responseCode);
|
||||
}
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuilder response = new StringBuilder();
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
// 将响应JSON字符串转换为LexMarkResultDTO对象
|
||||
LexMarkResultDTO<T> lexMarkResultDTO = JSON.parseObject(response.toString(), LexMarkResultDTO.class);
|
||||
if (lexMarkResultDTO.getResult() != 0) {
|
||||
log.error("利盟服务请求出错:{}", lexMarkResultDTO);
|
||||
throw new RRException(lexMarkResultDTO.toString());
|
||||
}
|
||||
|
||||
// 实例化param位data
|
||||
String param = lexMarkResultDTO.getParam();
|
||||
if (!StringUtils.isEmpty(param)) {
|
||||
try {
|
||||
T t = JSON.parseObject(param, clazz);
|
||||
lexMarkResultDTO.setData(t);
|
||||
}catch (Exception e){
|
||||
log.error("类型转换失败");
|
||||
throw new RRException("转换param位data时,类型与实际类型不匹配");
|
||||
}
|
||||
}
|
||||
|
||||
return lexMarkResultDTO;
|
||||
} catch (Exception e) {
|
||||
log.error("利盟服务请求失败:{}", lexMarkDTO, e);
|
||||
if (e instanceof RRException) {
|
||||
throw new RRException(((RRException) e).getCode(), e.getMessage());
|
||||
}
|
||||
throw new RRException("利盟服务请求失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 数据对象的data采用JSONObject进行接收
|
||||
*
|
||||
* @param lexMarkDTO 请求参数
|
||||
* @return result
|
||||
*/
|
||||
public LexMarkResultDTO<JSONObject> callDevice(LexMarkDTO lexMarkDTO) {
|
||||
return callDevice(lexMarkDTO, JSONObject.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
87
src/main/java/com/dpkj/common/utils/ThirdServiceUtil.java
Normal file
87
src/main/java/com/dpkj/common/utils/ThirdServiceUtil.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package com.dpkj.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultVO;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
/**
|
||||
* 第三方服务,主要是调用打印机等
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:45:01
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ThirdServiceUtil {
|
||||
|
||||
@Value("${app.custom.lexMarkServiceIp}")
|
||||
private String lexMarkServiceIp;
|
||||
@Value("${app.custom.lexMarkServicePort}")
|
||||
private String lexMarkServicePort;
|
||||
|
||||
/**
|
||||
* 利盟台式机-立体机 接口请求
|
||||
* @param lexMarkDTO 请求DTO
|
||||
* @return result
|
||||
*/
|
||||
public <T> T callDevice(LexMarkDTO lexMarkDTO, Class<T> responseType) {
|
||||
try {
|
||||
String urlStr = lexMarkServiceIp + ":" + lexMarkServicePort + "/CallDevice";
|
||||
URL url = new URL(urlStr);
|
||||
log.info("开始请求利盟服务,URL: {}, 请求体: {}", urlStr, JSON.toJSONString(lexMarkDTO));
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
// 将 LexMarkDTO 对象转换为 JSON 字符串
|
||||
String jsonInputString = JSON.toJSONString(lexMarkDTO);
|
||||
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
|
||||
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
|
||||
wr.write(input, 0, input.length);
|
||||
}
|
||||
int responseCode = connection.getResponseCode();
|
||||
log.info("利盟服务响应码: {}", responseCode);
|
||||
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||
throw new RRException("利盟服务请求失败,响应码:" + responseCode);
|
||||
}
|
||||
// 指定编码为 UTF-8
|
||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
String inputLine;
|
||||
StringBuilder response = new StringBuilder();
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
String responseStr = response.toString();
|
||||
log.info("利盟服务响应内容: {}", responseStr);
|
||||
// 将响应 JSON 字符串转换为泛型对象
|
||||
T result = JSON.parseObject(responseStr, responseType);
|
||||
if (result instanceof LexMarkResultVO && ((LexMarkResultVO) result).getResult() != 0) {
|
||||
throw new RRException(result.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("利盟服务请求发生异常", e);
|
||||
if (e instanceof RRException) {
|
||||
throw new RRException(((RRException) e).getCode(), e.getMessage());
|
||||
}
|
||||
throw new RRException("利盟服务请求失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dpkj.common.vo;
|
||||
|
||||
import com.dpkj.common.constant.CommonConst;
|
||||
import com.dpkj.common.exception.ErrorEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -49,7 +50,7 @@ public class Result<T> implements Serializable {
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(T data) {
|
||||
return error("", data);
|
||||
return ok("", data);
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(String msg, T data) {
|
||||
@@ -69,6 +70,14 @@ public class Result<T> implements Serializable {
|
||||
return error(CommonConst.SC_500, msg, null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(ErrorEnum errorEnum) {
|
||||
return error(errorEnum.getCode(), errorEnum.getMessage(), null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String message) {
|
||||
return error(code, message, null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String msg, T data) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setCode(code);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.dpkj.modules.barcode.controller;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.barcode.service.BarCodeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.controller
|
||||
* @Author: wzc
|
||||
* @Description: 条码读取
|
||||
* @CreateTime: 2025-02-10 15:21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("barcode")
|
||||
public class BarCodeController {
|
||||
|
||||
@Autowired
|
||||
private BarCodeService barcodeService;
|
||||
|
||||
/**
|
||||
* 条码扫描
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("scanBarcode")
|
||||
public Result scanBarcode() {
|
||||
return barcodeService.scanBarcode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.dpkj.modules.barcode.service;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
|
||||
public interface BarCodeService {
|
||||
|
||||
Result scanBarcode();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.dpkj.modules.barcode.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.constant.LexMarkConst;
|
||||
import com.dpkj.common.constant.MiddlewareFunctionsConst;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.utils.ThirdServiceUtil;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.barcode.service.BarCodeService;
|
||||
import com.dpkj.modules.readcard.vo.IDCardReadResultVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.service.impl
|
||||
* @Author: wzc
|
||||
* @Description:
|
||||
* @CreateTime: 2025-02-10 15:20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BarCodeServiceImpl implements BarCodeService {
|
||||
|
||||
@Autowired
|
||||
private ThirdServiceUtil thirdServiceUtil;
|
||||
|
||||
@Override
|
||||
public Result scanBarcode() {
|
||||
// 连接扫描仪
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setDevName(LexMarkConst.BARCODE_READER);
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(1000);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 90000);
|
||||
connectParam.put("ServiceName", LexMarkConst.BARCODE_READER);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
if (connectResult.getResult() == 0) {
|
||||
// 扫描条码
|
||||
LexMarkDTO scanBarcode = new LexMarkDTO();
|
||||
scanBarcode.setDevName(LexMarkConst.BARCODE_READER);
|
||||
scanBarcode.setActionName(MiddlewareFunctionsConst.SCAN_BARCODE);
|
||||
scanBarcode.setCallID(1000);
|
||||
JSONObject scanBarcodeParam = new JSONObject();
|
||||
scanBarcodeParam.put("BarcodeDataMode", 0);
|
||||
scanBarcodeParam.put("TimeOut", 0);
|
||||
scanBarcode.setParam(scanBarcodeParam.toJSONString());
|
||||
IDCardReadResultVO scanBarcodeResult = thirdServiceUtil.callDevice(scanBarcode, IDCardReadResultVO.class);
|
||||
if (scanBarcodeResult.getResult() == 0) {
|
||||
return Result.ok(scanBarcodeResult);
|
||||
} else {
|
||||
return Result.error("扫描异常!详情:" + connectResult.getDesc());
|
||||
}
|
||||
} else {
|
||||
return Result.error("扫描仪设备连接失败!详情:" + connectResult.getDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.dpkj.modules.keypad.controller;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.keypad.service.KeypadService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.controller
|
||||
* @Author: wzc
|
||||
* @Description: 数字键盘
|
||||
* @CreateTime: 2025-02-10 15:21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("keypad")
|
||||
public class KeypadController {
|
||||
|
||||
@Autowired
|
||||
private KeypadService keypadService;
|
||||
/**
|
||||
* 数字键盘 明文输入
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("inputData")
|
||||
public Result inputData() {
|
||||
return keypadService.inputData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消输入 (明文或者密文)
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("cancelInput")
|
||||
public Result CancelInput() {
|
||||
return keypadService.cancelInput();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.dpkj.modules.keypad.service;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
|
||||
public interface KeypadService {
|
||||
Result inputData();
|
||||
|
||||
Result cancelInput();
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.dpkj.modules.keypad.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.constant.LexMarkConst;
|
||||
import com.dpkj.common.constant.MiddlewareFunctionsConst;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.utils.ThirdServiceUtil;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.keypad.service.KeypadService;
|
||||
import com.dpkj.modules.keypad.util.WebSocketClient;
|
||||
import com.dpkj.modules.readcard.vo.IDCardReadResultVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.service.impl
|
||||
* @Author: wzc
|
||||
* @Description:
|
||||
* @CreateTime: 2025-02-10 15:20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class KeypadServiceImpl implements KeypadService {
|
||||
|
||||
@Autowired
|
||||
private ThirdServiceUtil thirdServiceUtil;
|
||||
|
||||
/**
|
||||
* 数字键盘 明文输入
|
||||
* 1. 连接数字键盘
|
||||
* 2. 明文输入
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result inputData() {
|
||||
log.info("开始执行密码输入流程");
|
||||
|
||||
// 连接数字键盘
|
||||
log.info("准备连接数字键盘设备");
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(1000);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 90000);
|
||||
connectParam.put("ServiceName", LexMarkConst.ENCRYPTOR);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
log.info("调用设备连接方法,参数: {}", connect);
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
log.info("设备连接结果: {}", connectResult);
|
||||
|
||||
WebSocketClient webSocketClient = null;
|
||||
try {
|
||||
if (connectResult.getResult() == 0) {
|
||||
log.info("数字键盘设备连接成功,准备进行明文输入");
|
||||
|
||||
// 明文输入
|
||||
LexMarkDTO plaintext = new LexMarkDTO();
|
||||
plaintext.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
plaintext.setActionName(MiddlewareFunctionsConst.INPUT_DATA);
|
||||
plaintext.setCallID(1000);
|
||||
JSONObject plaintextParam = new JSONObject();
|
||||
// 密码最小长度
|
||||
plaintextParam.put("MINLength", 0);
|
||||
// 密码最大长度
|
||||
plaintextParam.put("MAXLength", 6);
|
||||
// 是否自动结束
|
||||
plaintextParam.put("bAutoEnd", 1);
|
||||
// 超时时间
|
||||
plaintextParam.put("TimeOut", 30000);
|
||||
|
||||
plaintextParam.put("ActiveKeys", 81919);
|
||||
plaintextParam.put("TerminateKeys", 1024);
|
||||
plaintext.setParam(plaintextParam.toJSONString());
|
||||
log.info("调用明文输入方法,参数: {}", plaintext);
|
||||
|
||||
// 创建 WebSocket 客户端
|
||||
log.info("创建 WebSocket 客户端,连接地址: ws://127.0.0.1:12347");
|
||||
webSocketClient = new WebSocketClient("ws://127.0.0.1:12347");
|
||||
|
||||
IDCardReadResultVO plaintextResult = thirdServiceUtil.callDevice(plaintext, IDCardReadResultVO.class);
|
||||
log.info("明文输入操作结果: {}", plaintextResult);
|
||||
|
||||
if (plaintextResult.getResult() == 0) {
|
||||
log.info("明文输入成功,开始等待确认");
|
||||
try {
|
||||
// 适当延长等待时间
|
||||
while (true) {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
Boolean confirm = webSocketClient.getConfirm();
|
||||
if (confirm) {
|
||||
log.info("收到确认信息,结束等待");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
log.error("等待确认信息时被中断", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
String password = webSocketClient.getPassword();
|
||||
log.info("密码输入完成,密码为: {}", password);
|
||||
return Result.ok("密码输入完成!", password);
|
||||
} else {
|
||||
log.error("密码输入异常!详情:{}", connectResult.getDesc());
|
||||
return Result.error("密码输入异常!详情:" + connectResult.getDesc());
|
||||
}
|
||||
} else {
|
||||
log.error("数字键盘设备连接失败!详情:{}", connectResult.getDesc());
|
||||
return Result.error("数字键盘设备连接失败!详情:" + connectResult.getDesc());
|
||||
}
|
||||
} finally {
|
||||
if (webSocketClient != null) {
|
||||
log.info("关闭 WebSocket 客户端");
|
||||
webSocketClient.close();
|
||||
}
|
||||
// 关闭身份证读卡设备
|
||||
log.info("准备关闭数字键盘设备");
|
||||
LexMarkDTO close = new LexMarkDTO();
|
||||
close.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
close.setCallID(0);
|
||||
close.setActionName(MiddlewareFunctionsConst.CLOSE_CONNECTION);
|
||||
log.info("调用设备关闭方法,参数: {}", close);
|
||||
IDCardReadResultVO closeResult = thirdServiceUtil.callDevice(close, IDCardReadResultVO.class);
|
||||
log.info("设备关闭结果: {}", closeResult);
|
||||
if (closeResult.getResult() != 0) {
|
||||
log.error("数字键盘设备关闭异常!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 取消输入 (明文或者密文)
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result cancelInput() {
|
||||
LexMarkDTO cancelInput = new LexMarkDTO();
|
||||
cancelInput.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
cancelInput.setActionName(MiddlewareFunctionsConst.CANCEL_INPUT);
|
||||
cancelInput.setCallID(1000);
|
||||
cancelInput.setParam("{\"\"}");
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(cancelInput, IDCardReadResultVO.class);
|
||||
if (connectResult.getResult() == 0) {
|
||||
return Result.ok("取消输入 (明文或者密文)完成!");
|
||||
} else {
|
||||
return Result.error("取消输入 (明文或者密文)异常!详情:" + connectResult.getDesc());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
115
src/main/java/com/dpkj/modules/keypad/util/WebSocketClient.java
Normal file
115
src/main/java/com/dpkj/modules/keypad/util/WebSocketClient.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.dpkj.modules.keypad.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import javax.websocket.*;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ClientEndpoint
|
||||
public class WebSocketClient {
|
||||
|
||||
private Session session;
|
||||
// 密码
|
||||
private String password = "";
|
||||
// 是否确认
|
||||
private boolean confirm = false;
|
||||
|
||||
public WebSocketClient(String uri) {
|
||||
try {
|
||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||
session = container.connectToServer(this, new URI(uri));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session) {
|
||||
System.out.println("Connected to WebSocket server");
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message) {
|
||||
System.out.println("Received message: " + message);
|
||||
|
||||
// 解析外层 JSON 对象
|
||||
JSONObject outerObj = JSONObject.parseObject(message);
|
||||
|
||||
// 获取 "param" 字段对应的 JSON 对象
|
||||
JSONObject paramObj = outerObj.getJSONObject("param");
|
||||
|
||||
// 从 "param" 对象中获取 "Key" 的值
|
||||
Integer keyValue = paramObj.getInteger("Key");
|
||||
|
||||
if (keyValue != null) {
|
||||
// 更正
|
||||
if (keyValue == 8) {
|
||||
password = password.substring(0, password.length() - 1);
|
||||
// 取消
|
||||
} else if (keyValue == 27) {
|
||||
password = "";
|
||||
// 确认
|
||||
} else if (keyValue == 13) {
|
||||
confirm = true;
|
||||
} else if (keyValue == 2) {
|
||||
password += "00";
|
||||
} else {
|
||||
password += KEYPAD_MAPPING.get("0x" + Integer.toHexString(keyValue));
|
||||
}
|
||||
} else {
|
||||
System.out.println("未找到 Key 字段或其值为空。");
|
||||
}
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session, CloseReason closeReason) {
|
||||
System.out.println("Connection closed: " + closeReason.getReasonPhrase());
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public Boolean getConfirm() {
|
||||
return confirm;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
if (session != null && session.isOpen()) {
|
||||
session.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<String, String> KEYPAD_MAPPING = new HashMap<>();
|
||||
|
||||
static {
|
||||
// 初始化映射关系
|
||||
KEYPAD_MAPPING.put("0x30", "0");
|
||||
KEYPAD_MAPPING.put("0x31", "1");
|
||||
KEYPAD_MAPPING.put("0x32", "2");
|
||||
KEYPAD_MAPPING.put("0x33", "3");
|
||||
KEYPAD_MAPPING.put("0x34", "4");
|
||||
KEYPAD_MAPPING.put("0x35", "5");
|
||||
KEYPAD_MAPPING.put("0x36", "6");
|
||||
KEYPAD_MAPPING.put("0x37", "7");
|
||||
KEYPAD_MAPPING.put("0x38", "8");
|
||||
KEYPAD_MAPPING.put("0x39", "9");
|
||||
KEYPAD_MAPPING.put("0x08", "BACKSPACE"); // 更正按键
|
||||
KEYPAD_MAPPING.put("0x10", "CLEAR");
|
||||
KEYPAD_MAPPING.put("0x0D", "ENTER"); // 确认按键
|
||||
KEYPAD_MAPPING.put("0x1B", "CANCEL"); // 取消
|
||||
KEYPAD_MAPPING.put("0xA1", "HELP"); // 帮助
|
||||
KEYPAD_MAPPING.put("0x2E", "DECPOINT");
|
||||
KEYPAD_MAPPING.put("0x02", "00");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.dpkj.modules.print.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.print.service.PrintService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 挂号controller
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2025-02-08 11:49:46
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/print")
|
||||
public class RegisterController {
|
||||
|
||||
@Resource(name = "registerService")
|
||||
private PrintService printService;
|
||||
|
||||
/**
|
||||
* 挂号
|
||||
*/
|
||||
@PostMapping("/register/{templateName}")
|
||||
public Result<LexMarkResultDTO> register(@RequestParam String jsonData,
|
||||
@PathVariable String templateName,
|
||||
@RequestParam(defaultValue = "600") Integer width,
|
||||
@RequestParam(defaultValue = "950") Integer height
|
||||
){
|
||||
return Result.ok((LexMarkResultDTO)printService.printImage(JSONObject.parseObject(jsonData), templateName, width, height));
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂号,通过文件路径
|
||||
*/
|
||||
@PostMapping("/register")
|
||||
public Result<LexMarkResultDTO> registerByFilePath(@RequestParam(defaultValue = "D:\\images") String filePath){
|
||||
return Result.ok((LexMarkResultDTO)printService.printImage(null, null, 0, 0, filePath));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.dpkj.modules.print.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
/**
|
||||
* 打印服务接口
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:35:27
|
||||
*/
|
||||
public interface PrintService {
|
||||
|
||||
|
||||
/**
|
||||
* 生成小票图片
|
||||
*
|
||||
* @param data json数据,用来填充模板
|
||||
* @param template 模板(html字符串或者模板名称)
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @param saveDir 图片的保存路径,如果为空,那么不进行图片的保存
|
||||
*/
|
||||
Object printImage(JSONObject data, String template, int width, int height, String saveDir);
|
||||
|
||||
/**
|
||||
* 默认实现,给定一个默认可用的图片保存路径
|
||||
*/
|
||||
default Object printImage(JSONObject data, String template, int width, int height) {
|
||||
return printImage(data, template, width, height, "D:\\images");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.dpkj.modules.print.service.impl;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.utils.TemplateUtils;
|
||||
import com.dpkj.common.utils.ThirdService;
|
||||
import com.dpkj.modules.print.service.PrintService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thymeleaf.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 挂号服务打印
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:36:25
|
||||
*/
|
||||
@Service("registerService")
|
||||
public class RegisterServiceImpl implements PrintService {
|
||||
|
||||
@Resource
|
||||
private ThirdService thirdService;
|
||||
|
||||
@Override
|
||||
public LexMarkResultDTO<LexMarkResultDTO.Param> printImage(JSONObject data, String template, int width, int height, String saveDir) {
|
||||
StringBuilder filePath = new StringBuilder(saveDir);
|
||||
// 校验是否选中了模板,如果没选中模板的话则不需要另外生成了
|
||||
if ( !StringUtils.isEmpty(template) && !StringUtils.isEmpty(saveDir)){
|
||||
byte[] image = new TemplateUtils().generateReceiptImage(data, template, width, height, filePath);
|
||||
}
|
||||
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName("PrintForm");
|
||||
lexMarkDTO.setCallID(19256);
|
||||
lexMarkDTO.setDevName("ReceiptPrinter");
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("TimeOut", 30000);
|
||||
param.put("formName", "ReceiptForm");
|
||||
param.put("mediaName", "ReceiptMedia");
|
||||
param.put("alignment", 0);
|
||||
param.put("offsetX", 0);
|
||||
param.put("offsetY", 0);
|
||||
param.put("resolution", 1);
|
||||
param.put("mediaCtrl", 1);
|
||||
param.put("fields", "LOGO=" + filePath);
|
||||
lexMarkDTO.setParam(param.toJSONString());
|
||||
return thirdService.callDevice(lexMarkDTO, LexMarkResultDTO.Param.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.dpkj.modules.readcard.controller;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.readcard.service.ReadCardService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("readCard")
|
||||
public class ReadCardController {
|
||||
@Autowired
|
||||
private ReadCardService readCardService;
|
||||
|
||||
/**
|
||||
* 身份证读取
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("IDCardReader")
|
||||
public Result IDCardReader() {
|
||||
return readCardService.IDCardReader();
|
||||
}
|
||||
|
||||
/**
|
||||
* 社保卡读取
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("SocialSecurityCardReader")
|
||||
public Result SocialSecurityCardReader() {
|
||||
return readCardService.SocialSecurityCardReader();
|
||||
}
|
||||
|
||||
/**
|
||||
* 社保卡退卡
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("cardRefund")
|
||||
public Result cardRefund() {
|
||||
return readCardService.cardRefund();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dpkj.modules.readcard.service;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
|
||||
public interface ReadCardService {
|
||||
|
||||
Result IDCardReader();
|
||||
|
||||
Result SocialSecurityCardReader();
|
||||
|
||||
Result cardRefund();
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
package com.dpkj.modules.readcard.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.constant.LexMarkConst;
|
||||
import com.dpkj.common.constant.MiddlewareFunctionsConst;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.utils.ThirdService;
|
||||
import com.dpkj.common.utils.ThirdServiceUtil;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.readcard.service.ReadCardService;
|
||||
import com.dpkj.modules.readcard.vo.IDCardReadResultVO;
|
||||
import com.dpkj.modules.readcard.vo.SocialSecurityCardInfoVO;
|
||||
import com.dpkj.modules.readcard.vo.UserInfoVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.readcard.service.impl
|
||||
* @Author: wzc
|
||||
* @Description:
|
||||
* @CreateTime: 2025-02-07 10:21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ReadCardServiceImpl implements ReadCardService {
|
||||
|
||||
@Autowired
|
||||
private ThirdService thirdService;
|
||||
|
||||
@Autowired
|
||||
private ThirdServiceUtil thirdServiceUtil;
|
||||
|
||||
/**
|
||||
* 身份证读取
|
||||
* 1. 连接身份证读取设备
|
||||
* 2. 非接触身份证读取
|
||||
* 3. 关闭设备
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result IDCardReader() {
|
||||
Result result = null;
|
||||
log.info("开始执行身份证读取流程");
|
||||
try {
|
||||
log.info("准备连接非接身份证读卡模块");
|
||||
// 连接非接身份证读卡模块
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(19256);
|
||||
connect.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 30000);
|
||||
connectParam.put("ServiceName", LexMarkConst.ID_CARD_READ);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
log.info("调用设备连接方法,参数: {}", connect);
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
log.info("设备连接结果: {}", connectResult);
|
||||
if (connectResult.getResult() == 0) {
|
||||
log.info("设备连接成功,准备读取身份证");
|
||||
// 身份证读取
|
||||
LexMarkDTO read = new LexMarkDTO();
|
||||
read.setActionName(MiddlewareFunctionsConst.ACCEPT_AND_READ_TRACKS);
|
||||
read.setCallID(19256);
|
||||
read.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
JSONObject readParam = new JSONObject();
|
||||
readParam.put("TimeOut", 0);
|
||||
readParam.put("TrackMap", 776);
|
||||
read.setParam(readParam.toJSONString());
|
||||
log.info("调用设备读取方法,参数: {}", read);
|
||||
IDCardReadResultVO readResult = thirdServiceUtil.callDevice(read, IDCardReadResultVO.class);
|
||||
log.info("设备读取结果: {}", readResult);
|
||||
if (readResult.getResult() == 0) {
|
||||
log.info("身份证读取成功,开始解析身份证信息");
|
||||
IDCardReadResultVO.Param resultParam = JSON.parseObject(readResult.getParam().toString(), IDCardReadResultVO.Param.class);
|
||||
if (resultParam.getResult() == 0) {
|
||||
log.info("身份证信息解析成功,开始封装用户信息");
|
||||
UserInfoVO userInfoVO = new UserInfoVO();
|
||||
// 身份证基本信息 解析
|
||||
String[] array = Stream.of(resultParam.getChipdata().getDatas().split("\\|"))
|
||||
.filter(pair -> pair.contains("="))
|
||||
.map(pair -> pair.split("=")[1])
|
||||
.toArray(String[]::new);
|
||||
userInfoVO.setName(array[0]);
|
||||
userInfoVO.setSex(array[1]);
|
||||
userInfoVO.setNation(array[2]);
|
||||
userInfoVO.setBorn(array[3]);
|
||||
userInfoVO.setAddress(array[4]);
|
||||
userInfoVO.setIDCardNo(array[5]);
|
||||
userInfoVO.setGrantDept(array[6]);
|
||||
userInfoVO.setUserLifeBegin(array[7]);
|
||||
userInfoVO.setUserLifeEnd(array[8]);
|
||||
userInfoVO.setIDhead(array[9]);
|
||||
// 正面
|
||||
userInfoVO.setFrontimage(resultParam.getFrontimage().getDatas());
|
||||
// 反面
|
||||
userInfoVO.setBackimage(resultParam.getBackimage().getDatas());
|
||||
result = Result.ok(userInfoVO);
|
||||
log.info("用户信息封装成功,返回结果: {}", result);
|
||||
} else {
|
||||
result = Result.error("身份证读取失败!");
|
||||
log.error("身份证信息解析失败,返回结果: {}", result);
|
||||
}
|
||||
} else {
|
||||
result = Result.error(readResult.getDesc());
|
||||
log.error("身份证读取失败,错误信息: {}, 返回结果: {}", readResult.getDesc(), result);
|
||||
}
|
||||
} else {
|
||||
result = Result.error(connectResult.getDesc());
|
||||
log.error("设备连接失败,错误信息: {}, 返回结果: {}", connectResult.getDesc(), result);
|
||||
}
|
||||
} finally {
|
||||
log.info("准备关闭身份证读卡设备");
|
||||
// 关闭身份证读卡设备
|
||||
LexMarkDTO close = new LexMarkDTO();
|
||||
close.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
close.setCallID(0);
|
||||
close.setActionName(MiddlewareFunctionsConst.CLOSE_CONNECTION);
|
||||
log.info("调用设备关闭方法,参数: {}", close);
|
||||
IDCardReadResultVO closeResult = thirdServiceUtil.callDevice(close, IDCardReadResultVO.class);
|
||||
log.info("设备关闭结果: {}", closeResult);
|
||||
if (closeResult.getResult() != 0) {
|
||||
log.error("身份证读卡设备关闭异常!");
|
||||
}
|
||||
}
|
||||
log.info("身份证读取流程结束,最终返回结果: {}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 社保卡读取
|
||||
* 1. 连接社保卡读取设备
|
||||
* 2. 进卡读卡
|
||||
* 3. 读卡器上电
|
||||
* 4. 社保卡信息读取
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Result SocialSecurityCardReader() {
|
||||
log.info("开始执行社保卡读取流程");
|
||||
|
||||
// 社保卡读卡设备连接
|
||||
log.info("准备连接社保卡读卡设备");
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(19256);
|
||||
connect.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 30000);
|
||||
connectParam.put("ServiceName", LexMarkConst.CARD_READER);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
log.info("调用设备连接方法,参数: {}", connect);
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
log.info("设备连接结果: {}", connectResult);
|
||||
if (connectResult.getResult() == 0) {
|
||||
log.info("社保卡读卡设备连接成功,准备进卡");
|
||||
|
||||
// 进卡
|
||||
log.info("准备执行进卡操作");
|
||||
LexMarkDTO enterTheCard = new LexMarkDTO();
|
||||
enterTheCard.setActionName(MiddlewareFunctionsConst.ACCEPT_AND_READ_TRACKS);
|
||||
enterTheCard.setCallID(19256);
|
||||
enterTheCard.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject enterTheCardParam = new JSONObject();
|
||||
enterTheCardParam.put("DevType", 5);
|
||||
enterTheCardParam.put("TrackMap", 11);
|
||||
enterTheCardParam.put("TimeOut", 0);
|
||||
enterTheCard.setParam(enterTheCardParam.toJSONString());
|
||||
log.info("调用进卡方法,参数: {}", enterTheCard);
|
||||
IDCardReadResultVO enterTheCardResult = thirdServiceUtil.callDevice(enterTheCard, IDCardReadResultVO.class);
|
||||
log.info("进卡操作结果: {}", enterTheCardResult);
|
||||
if (enterTheCardResult.getResult() == 0) {
|
||||
log.info("进卡操作成功,准备上电");
|
||||
|
||||
// 上电
|
||||
log.info("准备执行上电操作");
|
||||
LexMarkDTO powerOn = new LexMarkDTO();
|
||||
powerOn.setActionName(MiddlewareFunctionsConst.CHIPPOWER);
|
||||
powerOn.setCallID(19256);
|
||||
powerOn.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject powerOnParam = new JSONObject();
|
||||
powerOnParam.put("PsamNo", 1);
|
||||
powerOnParam.put("ChipAction", 2);
|
||||
powerOn.setParam(powerOnParam.toJSONString());
|
||||
log.info("调用上电方法,参数: {}", powerOn);
|
||||
IDCardReadResultVO powerOnResult = thirdServiceUtil.callDevice(powerOn, IDCardReadResultVO.class);
|
||||
log.info("上电操作结果: {}", powerOnResult);
|
||||
if (powerOnResult.getResult() == 0) {
|
||||
log.info("上电操作成功,准备读取社保卡信息");
|
||||
|
||||
// 社保卡信息读取
|
||||
log.info("准备读取社保卡信息");
|
||||
LexMarkDTO socialSecurityCardReader = new LexMarkDTO();
|
||||
socialSecurityCardReader.setActionName(MiddlewareFunctionsConst.I_READ_CARD_BAS);
|
||||
socialSecurityCardReader.setCallID(19256);
|
||||
socialSecurityCardReader.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject socialSecurityCardReaderParam = new JSONObject();
|
||||
socialSecurityCardReaderParam.put("iType", 3);
|
||||
socialSecurityCardReader.setParam(socialSecurityCardReaderParam.toJSONString());
|
||||
log.info("调用读取社保卡信息方法,参数: {}", socialSecurityCardReader);
|
||||
IDCardReadResultVO socialSecurityCardReaderResult = thirdServiceUtil.callDevice(socialSecurityCardReader, IDCardReadResultVO.class);
|
||||
log.info("读取社保卡信息结果: {}", socialSecurityCardReaderResult);
|
||||
if (socialSecurityCardReaderResult.getResult() == 0) {
|
||||
log.info("社保卡信息读取成功,开始解析信息");
|
||||
|
||||
// 社保信息
|
||||
IDCardReadResultVO.SocialSecurityCard resultParam = JSON.parseObject(socialSecurityCardReaderResult.getParam().toString(), IDCardReadResultVO.SocialSecurityCard.class);
|
||||
String[] split = resultParam.getRerurnData().split("\\|");
|
||||
SocialSecurityCardInfoVO socialSecurityCardInfoVO = new SocialSecurityCardInfoVO();
|
||||
// 区号代码截取
|
||||
socialSecurityCardInfoVO.setAreaCode(split[0].substring(split[0].length() - 6));
|
||||
socialSecurityCardInfoVO.setSocialSecurityNo(split[1]);
|
||||
socialSecurityCardInfoVO.setCardNumber(split[2]);
|
||||
socialSecurityCardInfoVO.setIdentificationCode(split[3]);
|
||||
socialSecurityCardInfoVO.setName(split[4]);
|
||||
socialSecurityCardInfoVO.setCardResetInformation(split[5]);
|
||||
socialSecurityCardInfoVO.setSpecificationVersion(split[6]);
|
||||
socialSecurityCardInfoVO.setIssuanceDate(split[7]);
|
||||
socialSecurityCardInfoVO.setExpireDate(split[8]);
|
||||
socialSecurityCardInfoVO.setTerminalNumber(split[9]);
|
||||
socialSecurityCardInfoVO.setTerminalDeviceNumber(split[10]);
|
||||
log.info("社保卡信息解析完成,返回成功结果");
|
||||
return Result.ok(socialSecurityCardInfoVO);
|
||||
} else {
|
||||
log.error("社保卡信息读取失败,详情:{}", socialSecurityCardReaderResult.getDesc());
|
||||
return Result.error("社保卡信息读取失败!详情:" + socialSecurityCardReaderResult.getDesc());
|
||||
}
|
||||
} else {
|
||||
log.error("社保卡读取设备上电失败,详情:{}", powerOnResult.getDesc());
|
||||
return Result.error("社保卡读取设备上电失败!详情:" + powerOnResult.getDesc());
|
||||
}
|
||||
} else {
|
||||
log.error("社保卡读取设备进卡失败,详情:{}", enterTheCardResult.getDesc());
|
||||
return Result.error("社保卡读取设备进卡失败!详情:" + enterTheCardResult.getDesc());
|
||||
}
|
||||
} else {
|
||||
log.error("社保卡读取设备连接失败,详情:{}", connectResult.getDesc());
|
||||
return Result.error("社保卡读取设备连接失败!详情:" + connectResult.getDesc());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退卡并关闭设备
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result cardRefund() {
|
||||
log.info("开始执行社保卡退卡流程");
|
||||
|
||||
// 社保卡退卡
|
||||
log.info("准备发起社保卡退卡请求");
|
||||
LexMarkDTO cardRefund = new LexMarkDTO();
|
||||
cardRefund.setDevName(LexMarkConst.CARD_READER);
|
||||
cardRefund.setCallID(19256);
|
||||
cardRefund.setActionName(MiddlewareFunctionsConst.EJECT);
|
||||
JSONObject cardRefundParam = new JSONObject();
|
||||
cardRefundParam.put("position", 1);
|
||||
cardRefundParam.put("ejectpos", 1);
|
||||
cardRefund.setParam(cardRefundParam.toJSONString());
|
||||
log.info("调用设备退卡方法,参数: {}", cardRefund);
|
||||
IDCardReadResultVO cardRefundResult = thirdServiceUtil.callDevice(cardRefund, IDCardReadResultVO.class);
|
||||
log.info("设备退卡操作结果: {}", cardRefundResult);
|
||||
|
||||
if (cardRefundResult.getResult() == 0) {
|
||||
log.info("社保卡退卡成功,准备关闭社保卡读卡设备");
|
||||
|
||||
// 退卡成功再关闭社保卡读卡设备
|
||||
LexMarkDTO close = new LexMarkDTO();
|
||||
close.setDevName(LexMarkConst.CARD_READER);
|
||||
close.setCallID(0);
|
||||
close.setActionName(MiddlewareFunctionsConst.CLOSE_CONNECTION);
|
||||
log.info("调用设备关闭方法,参数: {}", close);
|
||||
IDCardReadResultVO closeResult = thirdServiceUtil.callDevice(close, IDCardReadResultVO.class);
|
||||
log.info("设备关闭操作结果: {}", closeResult);
|
||||
|
||||
if (closeResult.getResult() != 0) {
|
||||
log.error("社保卡读卡设备关闭异常!");
|
||||
}
|
||||
log.info("社保卡退卡流程完成,退卡成功");
|
||||
return Result.ok("退卡成功!");
|
||||
} else {
|
||||
log.error("退卡失败!请联系工作人员!");
|
||||
return Result.error("退卡失败!请联系工作人员!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package com.dpkj.modules.readcard.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 身份证读取模块返回值
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class IDCardReadResultVO<T> implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String msgName;
|
||||
|
||||
/**
|
||||
* 对应发送请求的callID。
|
||||
*/
|
||||
private int callID;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 发送请求中的actionName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 返回参数
|
||||
*/
|
||||
private T param;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Param {
|
||||
|
||||
/**
|
||||
* 请求ID
|
||||
*/
|
||||
private int RequestID;
|
||||
|
||||
/**
|
||||
* 身份证反面图像数据
|
||||
*/
|
||||
private Backimage backimage;
|
||||
|
||||
/**
|
||||
* 身份证基础信息
|
||||
*/
|
||||
private Chipdata chipdata;
|
||||
|
||||
/**
|
||||
* 指令ID
|
||||
*/
|
||||
private int dwCommandCode;
|
||||
|
||||
/**
|
||||
* 结束事件名称
|
||||
*/
|
||||
private String AcceptAndReadTracksOver;
|
||||
|
||||
/**
|
||||
* 事件ID
|
||||
*/
|
||||
private int eventType;
|
||||
|
||||
/**
|
||||
* 身份证正面图像数据
|
||||
*/
|
||||
private Frontimage frontimage;
|
||||
|
||||
/**
|
||||
* 服务ID
|
||||
*/
|
||||
private int hService;
|
||||
|
||||
/**
|
||||
* 读取结果 0成功 <0失败
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 调用的方法名称(操作函数)
|
||||
*/
|
||||
private String cmdName;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Backimage {
|
||||
/**
|
||||
* 身份证反面图像存储路径
|
||||
*/
|
||||
private String datas;
|
||||
|
||||
/**
|
||||
* 数据长度
|
||||
*/
|
||||
private int len;
|
||||
|
||||
/**
|
||||
* 返回的数据状态
|
||||
* DATAOK 读取正常
|
||||
* BLANK 空
|
||||
* INVALID 无效
|
||||
* NOTREAD 未读取
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Frontimage {
|
||||
/**
|
||||
* 身份证正面图像存储路径
|
||||
*/
|
||||
private String datas;
|
||||
|
||||
/**
|
||||
* 数据长度
|
||||
*/
|
||||
private int len;
|
||||
|
||||
/**
|
||||
* 返回的数据状态
|
||||
* DATAOK 读取正常
|
||||
* BLANK 空
|
||||
* INVALID 无效
|
||||
* NOTREAD 未读取
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Chipdata {
|
||||
/**
|
||||
* 身份证基本信息
|
||||
*/
|
||||
private String datas;
|
||||
|
||||
/**
|
||||
* 数据长度
|
||||
*/
|
||||
private int len;
|
||||
|
||||
/**
|
||||
* 返回的数据状态
|
||||
* DATAOK 读取正常
|
||||
* BLANK 空
|
||||
* INVALID 无效
|
||||
* NOTREAD 未读取
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class SocialSecurityCard {
|
||||
/**
|
||||
* 社保卡基本信息
|
||||
*/
|
||||
private String RerurnData;
|
||||
|
||||
/**
|
||||
* 社保卡读取响应信息
|
||||
*/
|
||||
private String msgerror;
|
||||
|
||||
/**
|
||||
* 社保卡读取响应结果 0成功 <0失败
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 调用的方法
|
||||
*/
|
||||
private String cmdName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.dpkj.modules.readcard.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 社保卡信息
|
||||
*/
|
||||
@Data
|
||||
public class SocialSecurityCardInfoVO {
|
||||
// 发卡地区行政区划代码
|
||||
private String areaCode;
|
||||
// 社会保障号码
|
||||
private String socialSecurityNo;
|
||||
// 卡号
|
||||
private String cardNumber;
|
||||
// 卡识别码
|
||||
private String identificationCode;
|
||||
// 姓名
|
||||
private String name;
|
||||
// 卡复位信息
|
||||
private String cardResetInformation;
|
||||
// 规范版本
|
||||
private String specificationVersion;
|
||||
// 发卡日期
|
||||
private String issuanceDate;
|
||||
// 卡有效期
|
||||
private String expireDate;
|
||||
// 终端机编号
|
||||
private String terminalNumber;
|
||||
// 终端设备号
|
||||
private String terminalDeviceNumber;
|
||||
}
|
||||
35
src/main/java/com/dpkj/modules/readcard/vo/UserInfoVO.java
Normal file
35
src/main/java/com/dpkj/modules/readcard/vo/UserInfoVO.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.dpkj.modules.readcard.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 身份证读取信息
|
||||
*/
|
||||
@Data
|
||||
public class UserInfoVO {
|
||||
// 姓名
|
||||
private String name;
|
||||
// 性别
|
||||
private String sex;
|
||||
// 名族
|
||||
private String nation;
|
||||
// 出生年月
|
||||
private String born;
|
||||
// 地址
|
||||
private String address;
|
||||
// 身份证号
|
||||
private String IDCardNo;
|
||||
// 签发机关
|
||||
private String grantDept;
|
||||
// 有效期起始日期
|
||||
private String userLifeBegin;
|
||||
// 有效期截止日期
|
||||
private String userLifeEnd;
|
||||
// 头像照片存储位置
|
||||
private String IDhead;
|
||||
// 证件正面照存储位置
|
||||
private String frontimage;
|
||||
// 证件反面面照存储位置
|
||||
private String backimage;
|
||||
|
||||
}
|
||||
@@ -25,3 +25,12 @@ server:
|
||||
enabled: true
|
||||
min-response-size: 1024
|
||||
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
|
||||
|
||||
|
||||
# 自定义app参数
|
||||
app:
|
||||
custom:
|
||||
lexMarkServiceIp: http://127.0.0.1
|
||||
lexMarkServicePort: 12346
|
||||
|
||||
|
||||
|
||||
41
src/main/resources/templates/hospital.html
Normal file
41
src/main/resources/templates/hospital.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>挂号单</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="font-size: 24px;">
|
||||
<div style="">
|
||||
<div style="text-align: center; font-size: 36px; font-weight: 700;"><span th:text="${hospitalName}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; font-size: 26px;">****<span th:text="${registeTerminalName}"></span></span>****</div>
|
||||
<div style="text-align: center; font-weight: 700; margin-bottom: -5px;">-----------------------------------------------------------------------------</div>
|
||||
<div style="text-align: center; font-size: 36px; font-weight: 700;"><span th:text="${registeType}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; margin-top: -7px;">-----------------------------------------------------------------------------</div>
|
||||
</div>
|
||||
<div style="font-weight: 700;">
|
||||
<div style="margin-left: 59px;">姓  名:<span th:text="${name}"></span></div>
|
||||
<div style="margin-left: 59px;">性  别:<span th:text="${gender}"></span></div>
|
||||
<div style="margin-left: 59px;">年  龄:<span th:text="${age}"></span></div>
|
||||
<div style="margin-left: 59px;">出生日期:<span th:text="${birthDate}"></span></div>
|
||||
<div style="margin-left: 59px;">卡  号:<span th:text="${cardNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">门 诊 号:<span th:text="${outpatientNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">就诊科室:<span th:text="${department}"></span></div>
|
||||
<div style="margin-left: 59px;">出诊级别:<span th:text="${visitLevel}"></span></div>
|
||||
<div style="margin-left: 59px;">就诊医生:<span th:text="${doctor}"></span></div>
|
||||
<div style="margin-left: 59px;">号  序:<span th:text="${sequence}"></span></div>
|
||||
<div style="margin-left: 59px;">挂号日期:<span th:text="${registerDate}"></span></div>
|
||||
<div style="margin-left: 59px; font-size: 31px; ">总费用:<span th:text="${totalFee}"></span> 元</div>
|
||||
<div style="margin-left: 59px;">支付方式:<span th:text="${paymentMethod}"></span></div>
|
||||
<div style="margin-left: 59px;">订 单 号:<span th:text="${orderNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">交易流水:<span th:text="${transactionNumber}"></span></div>
|
||||
<img style="margin-left: 35px; margin-top: -8px; margin-bottom: -8px;" th:src="${qrCodeBase64}" alt="QR Code"/>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-top: -20px; text-align: center; font-weight: 700;">-----------------------------------------------------------------------------</div>
|
||||
<div style="margin-left: 59px; font-weight: 700;">备注(REFERENCE):凭此条退费,请妥善保管!</div>
|
||||
<div style="margin-left: 59px;">终 端 号:<span th:text="${terminalNumber}"></span></div>
|
||||
<div style="margin-left: 59px;">打印时间:<span th:text="${printTime}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user