1 Commits
2.0 ... 1.0

Author SHA1 Message Date
91c7818dee 复制自助机模块的完善 2025-07-02 09:28:50 +08:00
35 changed files with 257 additions and 981 deletions

View File

@@ -1,27 +1,22 @@
@echo off
:: 医保程序地址
set WINEXE_CHSPATH=D:/Project/yinyitong-win/yinyitong.exe
:: 医保程序地址
:: ҽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
set CHSPATH=D:/Project/CHS
:: jar名称
:: jar<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
set NAME=yinyitong-dll-hang
:: 端口号
:: <EFBFBD>˿ں<EFBFBD>
set PROT=5946
echo 1、关闭端口进程%PROT%
echo <EFBFBD>ر<EFBFBD>%PROT%<EFBFBD>˿ڽ<EFBFBD><EFBFBD><EFBFBD>
for /f "tokens=1-5" %%i in ('netstat -ano^|findstr ":%PROT%"') do taskkill /pid %%m -t -f
echo 2、启动本地程序
cd /d %CHSPATH%/
start javaw.exe -Dfile.encoding=utf-8 -Djava.library.path="%CHSPATH%;%CHSPATH%/CHSInterfaceYn" -Dlog.path=%~dp0 -jar %~dp0\%NAME%.jar --server.port=%PROT%
echo <EFBFBD><EFBFBD><EFBFBD><EFBFBD>%NAME%
:: 延迟5秒
timeout /NOBREAK /T 5 >nul
cd %CHSPATH%
echo 3、启动银医通
start %WINEXE_CHSPATH%
start javaw.exe -Dfile.encoding=UTF-8 -Djava.library.path=%CHSPATH% -Dlog.path=%~dp0 -jar %~dp0\%NAME%.jar --server.port=%PROT%
echo <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
exit
::pause

148
pom.xml
View File

@@ -19,11 +19,18 @@
<properties>
<java.version>1.8</java.version>
<hutool.version>5.8.36</hutool.version>
<jna.version>5.17.0</jna.version>
<pdfbox.version>3.0.2</pdfbox.version>
<fastjson.version>1.2.83</fastjson.version>
<jna.version>5.17.0</jna.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@@ -34,19 +41,11 @@
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 数据校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -60,22 +59,11 @@
</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-jpms</artifactId>
<version>${jna.version}</version>
</dependency>
<!--<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>-->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform-jpms</artifactId>
@@ -100,7 +88,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
<version>${fastjson.version}</version>
</dependency>
<!-- thymeleaf-->
@@ -141,6 +129,12 @@
<version>3.1.28</version> <!-- 可以根据实际情况调整版本 -->
</dependency>
<!-- 数据校验-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!--微信支付-->
<dependency>
@@ -155,6 +149,7 @@
<artifactId>jdom2</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
@@ -164,18 +159,8 @@
<build>
<finalName>${project.artifactId}</finalName>
<!--<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/**</include>
</includes>
</resource>
</resources>-->
<plugins>
<!-- 只保留一个 spring-boot-maven-plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
@@ -190,106 +175,59 @@
</configuration>
</plugin>
<!-- 生成API文档插件 -->
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
</plugin>-->
<!--打jar包排除资源文件和依赖jar同时外部的lib、resource目录加入到classpath中 用命令java -jar运行jar时就不需要用-Dloader.path指定外部资源路径了 不需要spring-boot-maven-plugin插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!--MANIFEST.MF 中 Class-Path 加入前缀用命令java -jar运行jar时就不用-Dloader.path指定外部资源路径了-->
<classpathPrefix>lib/</classpathPrefix>
<!--jar包名字是否包含唯一版本标识-->
<useUniqueVersions>false</useUniqueVersions>
<!--指定含main方法的主类入口-->
<mainClass>com.dpkj.HangDllApplication</mainClass>
</manifest>
<manifestEntries>
<!--MANIFEST.MF 中 Class-Path 加入资源文件目录用命令java -jar时就不用-Dloader.path指定外部资源路径了 -->
<Class-Path>resources/</Class-Path>
</manifestEntries>
</archive>
<!-- 打包时从jar包里排除资源文件 -->
<excludes>
<!--<exclude>*.yml</exclude>
<exclude>*.xml</exclude>
<exclude>templates/**</exclude>
<exclude>win32-x86-64/**</exclude>
<exclude>win32-x86/**</exclude>-->
</excludes>
<!-- 指定项目打成jar包输出位置 -->
<outputDirectory>${project.build.directory}/output</outputDirectory>
</configuration>
</plugin>
<!-- 拷贝依赖jar包插件maven-jar-plugin只是打包排除文件 而把依赖jar包拷贝到外部lib目录就需要maven-dependency-plugin插件 -->
<!-- 拷贝依赖到 lib 目录 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/output/lib/</outputDirectory>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<!--拷贝资源文件! 插件maven-jar-plugin只负责打包时排除文件 而把资源文件拷贝到外部resource目录就需要maven-dependency-plugin插件-->
<!--<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
&lt;!&ndash;拷贝此目录下的所有文件到指定的外部目录。只负责拷贝而不是从jar包中排除&ndash;&gt;
<directory>src/main/resources</directory>
</resource>
</resources>
&lt;!&ndash; 把“<resource><directory>”指定目录中的文件输出到此处指定目录 &ndash;&gt;
<outputDirectory>${project.build.directory}/output/resources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>-->
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
<!-- 打包时将 resource 下的文件一起打包 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/**</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>dev</id>
<activation>
<!--默认激活配置-->
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!--测试环境-->
<profile.name>dev</profile.name>
</properties>
</profile>
<profile>
<id>pro</id>
<properties>
<!--正式环境-->
<profile.name>pro</profile.name>
</properties>
</profile>
</profiles>

View File

@@ -12,10 +12,10 @@ import java.net.UnknownHostException;
@Slf4j
@SpringBootApplication
public class HangDllApplication {
public class Application {
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext application = SpringApplication.run(HangDllApplication.class, args);
ConfigurableApplicationContext application = SpringApplication.run(Application.class, args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");

View File

@@ -1,22 +0,0 @@
package com.dpkj.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Auther: 萧道子
* @Date: 2024/4/28 14:55
* @Description:
*/
@Data
@Component
@ConfigurationProperties(prefix = "dpkj.chs")
public class ChsConfig {
/**
* 医保机构编码
*/
private String orgcode;
}

View File

@@ -1,22 +0,0 @@
package com.dpkj.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Auther: 萧道子
* @Date: 2024/4/28 14:55
* @Description:
*/
@Data
@Component
@ConfigurationProperties(prefix = "dpkj.his")
public class HisConfig {
/**
* 调用者ID
*/
private String operationId;
}

View File

@@ -1,45 +0,0 @@
package com.dpkj.common.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 接口返回数据格式
*/
@Data
@Accessors(chain = true)
public class ResultData implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 请求时间
*/
private String requestTime;
/**
* 请求内容
*/
private String requestContent;
/**
* 响应时间
*/
private String responseTime;
/**
* 响应内容
*/
private String responseContent;
/**
* 患者ID
*/
private String patientId;
/**
* 处理后的响应内容
*/
private Object result;
}

View File

@@ -75,7 +75,7 @@ public class ReceiptPrintController {
int dinyHeight = 0;
if (templateName.equals("department")) {
// 由于是使用的门诊小票-T2那么默认的高度为1100强行设置通过动态修改渲染的图片的高度
height = 1000;//根据实际情况调整
height = 900;//根据实际情况调整
// 单行最大长度为10
int singleLineMaxLength = 10;

View File

@@ -50,9 +50,9 @@ public class ReceiptPrintRequest implements Serializable {
private Integer width = 690;
/**
* 生成的模板的高度默认为1100
* 生成的模板的高度默认为1050
*/
private Integer height = 1100;
private Integer height = 1050;
}

View File

@@ -1,59 +0,0 @@
package com.dpkj.modules.chs.hischs.constant;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: 萧道子
* @Date: 2025/6/18 15:57
* @Description: 医保状态记录常量类
*/
public class ChsPayStateConst {
private static Map<String, Integer> chsPayState = new HashMap<String, Integer>(1);
/**
* 清除所有
*
* @return void
* @author 萧道子 2025/6/18
*/
public static void clear() {
chsPayState.clear();
}
/**
* 按key删除
*
* @return void
* @author 萧道子 2025/6/18
*/
public static void remove(String key) {
chsPayState.remove(key);
}
/**
* 添加
*
* @return void
* @author 萧道子 2025/6/18
*/
public static void put(String key, Integer val) {
chsPayState.put(key, val);
}
/**
* 获取
*
* @return void
* @author 萧道子 2025/6/18
*/
public static Integer get(String key) {
return chsPayState.get(key);
}
}

View File

@@ -1,137 +0,0 @@
package com.dpkj.modules.chs.hischs.controller;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.vo.Result;
import com.dpkj.common.vo.ResultData;
import com.dpkj.modules.chs.hischs.constant.ChsPayStateConst;
import com.dpkj.modules.chs.hischs.service.IHispayService;
import com.dpkj.modules.chs.hischs.vo.OutpatientBeginModel;
import com.dpkj.modules.chs.hischs.vo.OutpatientFinalModel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Auther: 萧道子
* @Date: 2025/3/22 16:25
* @Description: 医保模块-HIS医保
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/chs/hispay")
public class HispayController {
private final IHispayService hispayService;
/**
* 通过医保卡或医保电子凭证读卡
*
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/5/20
*/
@PostMapping("findReadCode")
public Result<?> findReadCode() {
try {
JSONObject res = hispayService.readCode();
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
log.error("[HispayController][getPatientInfo][按医保电子凭证读卡] ERR{}", e.getMessage());
return Result.error(e.getMessage());
}
}
/**
* 通过医保卡获取患者信息
*
* @param data :
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/5/28
*/
@PostMapping("findReadCard")
public Result<?> findReadCard(@RequestBody JSONObject data) {
try {
String password = data.getString("password");
if (StrUtil.isEmpty(password)) {
throw new RuntimeException("密码不可为空");
}
JSONObject res = hispayService.readCard(password);
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
log.error("[HispayController][readCardByCard][按医保卡读卡] ERR{}", e.getMessage());
return Result.error(e.getMessage());
}
}
/**
* 门诊缴费-预算
*
* @param data :
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/5/27
*/
@PostMapping("chsCodeAsOutpatientBegin")
public Result<?> chsCodeAsOutpatientBegin(@RequestBody @Validated OutpatientBeginModel data) {
try {
// 清空状态常量
ChsPayStateConst.clear();
log.info("[HispayController][chsCodeAsOutpatientBegin][门诊缴费-预算-电子医保凭证] 参数:{}", data);
ResultData res = hispayService.chsCodeAsOutpatientBegin(data);
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
log.info("[HispayController][chsCodeAsOutpatientBegin][门诊缴费-预算-电子医保凭证] 失败:{}", e.getMessage());
return Result.error(e.getMessage());
}
}
/**
* 门诊缴费-结算
*
* @param data :
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/5/27
*/
@PostMapping("chsCodeAsOutpatientFinal")
public Result<?> chsCodeAsOutpatientFinal(@RequestBody @Validated OutpatientFinalModel data) {
try {
log.info("[HispayController][chsCodeAsOutpatientFinal][门诊缴费-结算-电子医保凭证] 参数:{}", data);
ResultData res = hispayService.chsCodeAsOutpatientFinal(data);
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
log.info("[HispayController][chsCodeAsOutpatientFinal][门诊缴费-结算-电子医保凭证] 失败:{}", e.getMessage());
return Result.error(e.getMessage());
}
}
/**
* 获取医保支付状态
*
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/6/18
*/
@PostMapping("getChsPayState")
public Result<?> getChsPayState(@RequestBody OutpatientBeginModel data) {
String no = data.getPrescriptionNo();
if (StrUtil.isEmpty(no)) {
return Result.error("收据号不可为空");
}
Integer num = ChsPayStateConst.get(no);
return Result.ok("成功", num);
}
}

View File

@@ -1,46 +0,0 @@
package com.dpkj.modules.chs.hischs.service;
import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.vo.ResultData;
import com.dpkj.modules.chs.hischs.vo.OutpatientBeginModel;
import com.dpkj.modules.chs.hischs.vo.OutpatientFinalModel;
public interface IHispayService {
/**
* 通过医保电子凭证读卡
*
* @return com.alibaba.fastjson.JSONObject
* @author 萧道子 2025/5/28
*/
JSONObject readCode();
/**
* 通过医保卡-读卡
*
* @return com.alibaba.fastjson.JSONObject
* @author 萧道子 2025/5/28
*/
JSONObject readCard(String password);
/**
* 门诊缴费-预算 电子凭证支付
*
* @param data :
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/5/27
*/
ResultData chsCodeAsOutpatientBegin(OutpatientBeginModel data);
/**
* 门诊缴费-结算 电子凭证支付
*
* @param data :
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/5/27
*/
ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data);
}

View File

@@ -1,269 +0,0 @@
package com.dpkj.modules.chs.hischs.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.config.HisConfig;
import com.dpkj.common.vo.ResultData;
import com.dpkj.modules.chs.hischs.constant.ChsPayStateConst;
import com.dpkj.modules.chs.hischs.service.IHispayService;
import com.dpkj.modules.chs.hischs.vo.OutpatientBeginModel;
import com.dpkj.modules.chs.hischs.vo.OutpatientFinalModel;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import javax.annotation.PostConstruct;
import java.util.Map;
/**
* @Auther: 萧道子
* @Date: 2025/3/22 16:29
* @Description:
*/
@Slf4j
@Service
// @AllArgsConstructor
public class HispayServiceImpl implements IHispayService {
// COM对象
private static ActiveXComponent dispatch;
@PostConstruct
public void postConstruct() {
dispatch = instanceActive();
}
/**
* 获取HIS医保实例
*
* @return com.jacob.activeX.ActiveXComponent
* @author 萧道子 2025/5/21
*/
private static ActiveXComponent instanceActive() {
try {
// 初始化
// ComThread.InitSTA(); //容易导致线程发生阻塞
ActiveXComponent activeXComponent = new ActiveXComponent("PayClient.clsPayClient");
log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载成功");
return activeXComponent;
} catch (UnsatisfiedLinkError e) {
log.error("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载失败:{}", e.getMessage());
throw new RuntimeException("HIS医保COM库加载失败" + e.getMessage(), e);
}
}
/**
* 释放资源
*
* @return void
* @author 萧道子 2025/5/21
*/
private void releaseActive() {
// ComThread.Release(); //容易导致线程发生阻塞
}
/**
* 处理参数
*
* @param params : 请求参数
* @param password : 密码
* @return java.lang.String
* @author 萧道子 2025/5/27
*/
private String processParameters(JSONObject params, String password) {
JSONObject req = new JSONObject() {{
put("timestamp", ""); // 请求发送时间 DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")
put("requestid", ""); // 唯一请求id IDGenerator.getSnowflakeIdToStr()
put("operid", ""); // 调用者代码 hisConfig.getOperationId()
put("password", password); // 密码
put("params", params);
}};
Document document = XmlUtil.mapToXml(req, "request");
return XmlUtil.toStr(document, "UTF-8", false, true);
}
/**
* 校验结果
*
* @param resStr :
* @return com.alibaba.fastjson.JSONObject
* @author 萧道子 2025/5/28
*/
private JSONObject verifyResult(String resStr) {
if (StrUtil.isBlank(resStr)) {
throw new RuntimeException("信息获取失败");
}
Map<String, Object> resMap = XmlUtil.xmlToMap(resStr);
JSONObject resJson = new JSONObject(resMap);
if (StrUtil.equals(resJson.getString("resultCode"), "1")) {
throw new RuntimeException(resJson.getString("resultMessage"));
}
if (!resJson.containsKey("result")) {
throw new RuntimeException("result数据为空");
}
return resJson.getJSONObject("result");
}
@Override
public JSONObject readCode() {
/** 1、组装参数 */
JSONObject val = new JSONObject()
.fluentPut("cardtype", "9") // 1.就诊卡2.医保卡5.门诊号6.患者姓名和电话号码8.电子健康码/卡9.医保电子凭证
.fluentPut("cardno", "") // 患者就诊卡号
.fluentPut("sfzh", "") // 身份证号
.fluentPut("hzxm", "") // 患者姓名
.fluentPut("phone", ""); // 患者电话号码
String params = processParameters(val, null);
log.debug("[HispayServiceImpl][readCode][医保读卡-电子凭证] 接口入参:{}", params);
/** 2、调用COM函数 */
Variant vres = new Variant("", true);
Variant call = Dispatch.call(dispatch, "fRun", "BMZXX010", params, vres);
String resStr = vres.getStringRef();
log.debug("[HispayServiceImpl][readCode][医保读卡-电子凭证] call返回值{} 结果:{}", call, resStr);
/** 3、处理读卡结果 */
JSONObject result = verifyResult(resStr);
if (!result.containsKey("item")) {
throw new RuntimeException("item数据为空");
}
return result.getJSONObject("item");
}
@Override
public JSONObject readCard(String password) {
/** 1、组装参数 */
JSONObject val = new JSONObject()
.fluentPut("cardtype", "2") // 1.就诊卡2.医保卡5.门诊号6.患者姓名和电话号码8.电子健康码/卡9.医保电子凭证
.fluentPut("cardno", "") // 患者就诊卡号
.fluentPut("sfzh", "") // 身份证号
.fluentPut("hzxm", "") // 患者姓名
.fluentPut("phone", ""); // 患者电话号码
String params = processParameters(val, password);
log.debug("[HispayServiceImpl][readCard][医保读卡-医保卡] 接口入参:{}", params);
/** 2、调用COM函数 */
Variant vres = new Variant("", true);
Variant call = Dispatch.call(dispatch, "fRun", "BMZXX010", params, vres);
String resStr = vres.getStringRef();
log.debug("[HispayServiceImpl][readCard][医保读卡-医保卡] call返回值{} 结果:{}", call, resStr);
/** 3、处理读卡结果 */
JSONObject result = verifyResult(resStr);
if (!result.containsKey("item")) {
throw new RuntimeException("item数据为空");
}
return result.getJSONObject("item");
}
private ResultData outpatientBudget(OutpatientBeginModel data) {
/** 1、组装参数 */
JSONObject val = new JSONObject()
.fluentPut("patid", data.getPatientId()) // 病人ID
.fluentPut("cfxhhj", data.getPrescriptionNo()) // 划价单据,格式:单据1,单据2,单据3
.fluentPut("czksfbz", "0") // 是否扣院内账户0不使用院内账户1使用院内账户默认不使用院内账户
.fluentPut("zfjsbz", "0") // 是否自费结算0根据医保代码缴费1自费结算默认自费结算
.fluentPut("ybrc", ""); // 医保入参xml节点
String params = processParameters(val, data.getPassword());
log.debug("[HispayServiceImpl][outpatientBudget][门诊缴费-预算] 接口入参:{}", params);
String requestTime = DateUtil.now();
/** 2、调用COM函数 */
Variant resVariant = new Variant("", true);
Variant call = Dispatch.call(dispatch, "fRun", "BMZJF001", params, resVariant);
String responseTime = DateUtil.now();
String resStr = resVariant.getStringRef();
log.debug("[HispayServiceImpl][outpatientBudget][门诊缴费-预算] call返回值{} 结果:{}", call, resStr);
/** 3、处理结果 */
JSONObject result = verifyResult(resStr);
return new ResultData()
.setRequestTime(requestTime)
.setRequestContent(params)
.setResponseTime(responseTime)
.setPatientId(data.getPatientId())
.setResponseContent(resStr)
.setResult(result);
}
@Override
public ResultData chsCodeAsOutpatientBegin(OutpatientBeginModel data) {
// 用户读卡-生成token
JSONObject userInfo = readCode();
String patientId = userInfo.getString("patid");
data.setPatientId(patientId);
// 更新常量状态 已读卡
ChsPayStateConst.put(data.getPrescriptionNo(), 1);
return outpatientBudget(data);
}
@Override
public ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data) {
/** 1、组装参数 */
String requestTime = DateUtil.now();
data.setPaytime(requestTime);
JSONObject val = ((JSONObject) JSON.toJSON(data))
.fluentPut("czksfbz", "0") // 是否扣院内账户,与预算保持一致
.fluentPut("zfjsbz", "0") // 是否自费结算与预算保持一致0根据病人医保代码结算1自费结算
.fluentPut("ybrc", "")
.fluentPut("ptlsh", "")
.fluentPut("jysm", "");
String params = processParameters(val, null);
log.debug("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] 接口入参:{}", params);
/** 2、调用COM函数 */
Variant resVariant = new Variant("", true);
Variant call = Dispatch.call(dispatch, "fRun", "BMZJF002", params, resVariant);
String responseTime = DateUtil.now();
String resStr = resVariant.getStringRef();
log.debug("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] call返回值{} 结果:{}", call, resStr);
/** 3、处理结果 */
JSONObject result = verifyResult(resStr);
return new ResultData()
.setRequestTime(requestTime)
.setRequestContent(params)
.setResponseTime(responseTime)
.setPatientId(data.getPatid())
.setResponseContent(resStr)
.setResult(result);
}
}

View File

@@ -1,37 +0,0 @@
package com.dpkj.modules.chs.hischs.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
/**
* @Auther: 萧道子
* @Date: 2025/5/27 16:52
* @Description:
*/
@Data
@Accessors(chain = true)
public class OutpatientBeginModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 病人ID
*/
// @NotEmpty(message = "患者ID不可为空!")
private String patientId;
/**
* 处方单号 - 多个逗号拼接
*/
@NotEmpty(message = "处方单号不可为空!")
private String prescriptionNo;
/**
* 病人ID
*/
// @NotEmpty(message = "密码不可为空!")
private String password;
}

View File

@@ -1,49 +0,0 @@
package com.dpkj.modules.chs.hischs.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
/**
* @Auther: 萧道子
* @Date: 2025/5/27 16:52
* @Description: 结算
*/
@Data
@Accessors(chain = true)
public class OutpatientFinalModel implements Serializable {
private static final long serialVersionUID = 1L;
@NotEmpty(message = "患者ID不可为空!")
private String patid;
@NotEmpty(message = "收据号不可为空!")
private String sjh;
@NotEmpty(message = "总金额不可为空!")
private String zje;
@NotEmpty(message = "应付金额不可为空!")
private String ysje;
@NotEmpty(message = "支付方式不可为空!")
private String paytype;
@NotEmpty(message = "支付金额不可为空!")
private String paymoney;
@NotEmpty(message = "支付流水号不可为空!")
private String paylsh;
@NotEmpty(message = "医保报销金额不可为空!")
private String ybzf;
/**
* 支付时间
*/
// @NotEmpty(message = "支付时间不可为空!")
private String paytime;
}

View File

@@ -1,19 +1,13 @@
package com.dpkj.modules.scanface.ali.controller;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.vo.Result;
import com.dpkj.modules.scanface.ali.config.AliFaceConfig;
import com.dpkj.modules.scanface.ali.constants.AliFaceConstants;
import com.dpkj.modules.scanface.ali.dll.AbcpInvoke;
import com.dpkj.modules.scanface.ali.service.IAliScanFaceService;
import com.dpkj.modules.scanface.ali.vo.AliOrderVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -22,8 +16,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.File;
import java.util.Map;
/**
* @Auther: 萧道子

View File

@@ -1,6 +1,5 @@
package com.dpkj.modules.scanface.ali.dll;
import com.dpkj.common.vo.Result;
import com.sun.jna.Callback;
import com.sun.jna.Native;
import lombok.extern.slf4j.Slf4j;
@@ -33,7 +32,7 @@ public class AbcpInvoke {
msAbcpNativeDll = (AbcpNativeDll) Native.load(fileDylib, AbcpNativeDll.class);
} catch (Throwable e) {
msAbcpNativeDll = null;
log.error("## 本地库未加载,返回错误 ERROR :{},{} ", fileDylib, e.getMessage());
log.error("## 本地库未加载,返回错误 ERROR : load. ## [%s][%s] %n", fileDylib, e.getMessage());
}
} else {
log.error("## ERROR : dylib NOT exist ## %s %n", fileDylib);

View File

@@ -4,8 +4,8 @@ import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.vo.Result;
import com.dpkj.modules.scanface.ali.config.AliFaceConfig;
import com.dpkj.modules.scanface.ali.constants.AliFaceConstants;
@@ -16,8 +16,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.util.HashMap;
@@ -44,6 +44,20 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
private AliFaceConfig aliFaceConfig;
/**
* 资源初始化
* 把刷脸初始化加到项目启动时先初始化一次,防止首次调用刷脸初始化过慢的问题
*/
@PostConstruct
public void postConstruct() {
log.info("[AliScanFaceServiceImpl][postConstruct][支付宝刷脸DLL] 初始化动态链接库");
try {
this.iniAbcpAbsolute();
} catch (Exception e) {
log.info("[AliScanFaceServiceImpl][postConstruct][56][支付宝刷脸初始化失败:] {}", e.getMessage());
}
}
/**
* @description: * 完整的统一的支付宝刷脸支付
* 1、调用硬件刷脸获取到ftoken
@@ -57,40 +71,52 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
public Result<JSONObject> aliFacePay(AliOrderVo aliOrderVo) {
try {
/**
* 1、获取刷脸"刷脸去初始化服务"的ftoken返回值
* 0、执行ABCP初始化
*/
this.iniAbcpAbsolute();
//参数
JSONObject zolozConfig = new JSONObject().fluentPut("installAngle", 90);
JSONObject params = new JSONObject()
.fluentPut("serviceId", aliFaceConfig.getServiceId())
.fluentPut("zolozConfig", zolozConfig);
String json = params.toJSONString();
String service_code = AliFaceConstants.SMILEVERIFYNIN_V1; //调用的组件编码:初始化
Result<Object> startServiceIniResult = this.startServiceIni(json, service_code);
if (startServiceIniResult.isSuccess()) {
Map<String, String> res = (Map<String, String>) startServiceIniResult.getResult();
String ftoken = res.get("ftoken");
Result<Object> result = this.iniAbcpAbsolute();
if (result.isSuccess()) {
/**
* 2、调用后端的支付宝统一收单交易支付接口、存入hisPay
* 1、获取刷脸"刷脸去初始化服务"的ftoken返回值
*/
aliOrderVo.setAuthCode(ftoken);//Demo值"fp128d26333fa66e66e7f34c493d30cdh76"
JSONObject serverParams = (JSONObject) JSON.toJSON(aliOrderVo);
//参数
JSONObject zolozConfig = new JSONObject().fluentPut("installAngle", 90);
JSONObject params = new JSONObject()
.fluentPut("serviceId", aliFaceConfig.getServiceId())
.fluentPut("zolozConfig", zolozConfig);
String json = params.toJSONString();
String service_code = AliFaceConstants.SMILEVERIFYNIN_V1; //调用的组件编码:初始化
Result<Object> startServiceIniResult = this.startServiceIni(json, service_code);
log.info("[AliScanFaceServiceImpl][aliFacePay][72][1、获取刷脸去初始化服务的结果] {}", startServiceIniResult.toString());
if (startServiceIniResult.isSuccess()) {
Map<String, String> res = (Map<String, String>) startServiceIniResult.getResult();
String ftoken = res.get("ftoken");
log.info("[AliScanFaceServiceImpl][aliFacePay][76][[1、获取刷脸去初始化服务的结果-ftoken值] {}", ftoken);
String url = serverUrl + "openapi/aliPayOrderApi/createOrder";
String req = HttpRequest.post(url)
.header(Header.CONTENT_TYPE, ContentType.JSON.toString(CharsetUtil.CHARSET_UTF_8))
.body(serverParams.toJSONString())
.execute()
.body();
JSONObject serverResult = JSONObject.parseObject(req);
/**
* 2、调用后端的支付宝统一收单交易支付接口、存入hisPay
*/
aliOrderVo.setAuthCode(ftoken);//Demo值"fp128d26333fa66e66e7f34c493d30cdh76"
JSONObject serverParams = (JSONObject) JSON.toJSON(aliOrderVo);
log.info("[AliScanFaceServiceImpl][aliFacePay][83][调用后端的支付宝统一收单交易支付接口参数] {}", serverParams.toString());
return Result.ok(serverResult);
} else {
//调用ABCP 刷脸初始化服务失败
log.error("[AliScanFaceServiceImpl][aliFacePay][299]调用ABCP 刷脸初始化服务失败 {}", startServiceIniResult.getMessage());
return Result.error(startServiceIniResult.getMessage());
String url = serverUrl + "openapi/aliPayOrderApi/createOrder";
log.info("[AliScanFaceServiceImpl][aliFacePay][86][调用后端的支付宝统一收单交易支付接口路径] {}", url);
String req = HttpRequest.post(url)
.header(Header.CONTENT_TYPE, ContentType.JSON.toString(CharsetUtil.CHARSET_UTF_8))
.body(serverParams.toJSONString())
.execute()
.body();
JSONObject serverResult = JSONObject.parseObject(req);
log.info("[AliScanFaceServiceImpl][aliFacePay][93][调用后端的支付宝统一收单交易支付接口结果] {}", serverResult.toString());
return Result.ok(serverResult);
} else {
//调用ABCP 刷脸初始化服务失败
log.error("[AliScanFaceServiceImpl][aliFacePay][299]调用ABCP 刷脸初始化服务失败 {}", startServiceIniResult.getMessage());
return Result.error(startServiceIniResult.getMessage());
}
}else {
return Result.error("执行iniAbcpAbsolute初始化失败");
}
} catch (Exception e) {
e.printStackTrace();
@@ -126,23 +152,59 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
//指定支付宝LOT SDK的本地库路径
AbcpInvoke.SetAPIPathFile(aliFaceConfig.getDllPath());
// 使用 CountDownLatch 实现线程同步
CountDownLatch latch = new CountDownLatch(1);
CountDownLatch latchFinish = new CountDownLatch(1);
//获取返回数据
AtomicReference<Integer> processCode = new AtomicReference<>();
AtomicReference<String> processResult = new AtomicReference<>();
AtomicReference<Integer> finishCode = new AtomicReference<>();
AtomicReference<String> finishResult = new AtomicReference<>();
//创建回调实例
AbcpInvoke.CallbackRsp callbackRsp = new AbcpInvoke.CallbackRsp() {
@Override
public void OnProcess(int code, String subCode, String subMsg, String result) {
log.info("[AliScanFaceServiceImpl][OnProcess][123][ABCP调用iniAbcpAbsolute][code:{}][subCode:{}][subMsg:{}][result:{}]", code, subCode, subMsg, result);
log.info("[AliScanFaceServiceImpl][OnProcess][155][0、ABCP调用iniAbcpAbsolute-OnProcess][code:{}][subCode:{}][subMsg:{}][result:{}] ", code, subCode, subMsg, result);
try {
processCode.set(code);
processResult.set(result);
} finally {
latch.countDown(); // 确保无论如何都释放锁
}
}
@Override
public void OnFinish(int code, String subCode, String subMsg, String result) {
log.info("[AliScanFaceServiceImpl][OnFinish][128][ABCP调用iniAbcpAbsolute][code:{}][subCode:{}][subMsg:{}][result:{}]", code, subCode, subMsg, result);
log.info("[AliScanFaceServiceImpl][OnFinish][167][0、ABCP调用iniAbcpAbsolute-OnFinish][code:{}][subCode:{}][subMsg:{}][result:{}]", code, subCode, subMsg, result);
try {
finishCode.set(code);
finishResult.set(result);
} finally {
latchFinish.countDown(); // 确保无论如何都释放锁
}
}
};
//初始化
log.info("[AliScanFaceServiceImpl][iniAbcpAbsolute][175][0、ABCP调用iniAbcpAbsolute初始化参数][appId:{}][appVersion:{}][json:{}] ", aliFaceConfig.getAppId(), aliFaceConfig.getAppVersion(), json);
AbcpInvoke.AbcpInit(aliFaceConfig.getAppId(), aliFaceConfig.getAppVersion(), json, callbackRsp);
return Result.ok("支付宝ABCP初始化成功");
// 等待finish回调完成设置超时避免死锁
boolean awaitFinishSuccess = latchFinish.await(120, TimeUnit.SECONDS);
if (!awaitFinishSuccess) {
log.info("[AliScanFaceServiceImpl][iniAbcpAbsolute][181] [0、ABCP调用iniAbcpAbsolute初始化-120秒-等待finish回调超时]");
return Result.error("初始化等待finish回调超时");
} else {
JSONObject jsonObject = JSONObject.parseObject(finishResult.get());
log.info("[AliScanFaceServiceImpl][iniAbcpAbsolute][184][0、ABCP调用iniAbcpAbsolute初始化-finish回调结果-finishCode {}] [返回结果:{}]", finishCode, jsonObject.toString());
if (finishCode.get() == 1000) {
return Result.ok("ABCP调用iniAbcpAbsolute初始化成功");
} else {
return Result.error("ABCP调用刷脸初始化服务finish失败");
}
}
} else {
log.info("[AliScanFaceServiceImpl][iniAbcpAbsolute][55][{} :文件不存在]", aliFaceConfig.getDllPath());
return Result.error("支付宝ABCP初始化失败" + aliFaceConfig.getDllPath() + "不存在");
@@ -217,10 +279,13 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
// 等待process回调完成设置超时避免死锁
boolean awaitSuccess = latch.await(10, TimeUnit.SECONDS);
if (!awaitSuccess) {
log.info("[AliScanFaceServiceImpl][startServiceIni][226][10秒-等待process回调超时]");
return Result.error("等待process回调超时");
} else {
log.info("[AliScanFaceServiceImpl][startServiceIni][229][ABCP调用刷脸初始化服务-process回调结果-processCode] {}", processCode);
if (processCode.get() == 0) {
JSONObject jsonObject = JSONObject.parseObject(processResult.get());
log.info("[AliScanFaceServiceImpl][startServiceIni][232][ABCP调用刷脸初始化服务-process回调结果] {}", jsonObject.toString());
if (jsonObject.containsKey("traceId")) {
res.put("traceId", jsonObject.getString("traceId"));
} else {
@@ -234,10 +299,13 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
// 等待finish回调完成设置超时避免死锁
boolean awaitFinishSuccess = latchFinish.await(120, TimeUnit.SECONDS);
if (!awaitFinishSuccess) {
log.info("[AliScanFaceServiceImpl][startServiceIni][246][120秒-等待finish回调超时]");
return Result.error("等待finish回调超时");
} else {
log.info("[AliScanFaceServiceImpl][startServiceIni][249][ABCP调用刷脸初始化服务-finish回调结果-finishCode] {}", finishCode);
if (finishCode.get() == 1000) {
JSONObject jsonObject = JSONObject.parseObject(finishResult.get());
log.info("[AliScanFaceServiceImpl][startServiceIni][252][ABCP调用刷脸初始化服务-finish回调结果] {}", jsonObject.toString());
if (jsonObject.containsKey("ftoken")) {
res.put("ftoken", jsonObject.getString("ftoken"));//ftoken参数的有效期为2分钟
res.put("barCode", jsonObject.getString("barCode"));
@@ -251,6 +319,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
}
//结果返回
log.info("[AliScanFaceServiceImpl][startServiceIni][266][][ABCP调用刷脸初始化服务成功返回结果] {}", finishResultRef.get());
return finishResultRef.get();
} catch (Exception e) {
e.printStackTrace();

View File

@@ -37,7 +37,7 @@ public class AliOrderVo implements Serializable {
private String outTradeNo;
/**
* 用户支付金额
* 用户支付金额 单位元
*/
//@ApiModelProperty(value = "用户支付金额")
private String totalAmount;

View File

@@ -18,6 +18,7 @@ import com.dpkj.modules.scanface.wx.vo.WxFacePayAuthinfoResp;
import com.dpkj.modules.scanface.wx.vo.WxFacePayReq;
import com.dpkj.modules.scanface.wx.vo.WxFacePayResp;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.bean.request.WxPayOrderReverseRequest;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
@@ -33,9 +34,16 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @description: 微信刷脸支付
@@ -71,10 +79,6 @@ public class WxFacePayController {
public Result<String> doFacePay(@RequestBody WxFaceOrderVo wxFaceOrderVo) throws Exception {
Result<String> result = new Result<>();
try {
//元转分
int money = new BigDecimal(wxFaceOrderVo.getTotalAmount()).multiply(new BigDecimal(100)).intValue();
wxFaceOrderVo.setTotalAmount(String.valueOf(money));
//1 初始化
this.initWxpayface();
@@ -91,7 +95,6 @@ public class WxFacePayController {
WxPayMicropayResult micropayResult = new WxPayMicropayResult();
if (StringUtil.isNotBlank(authinfoResp.getFace_code())) {
//5、调用后台人脸支付API发起支付
System.out.println("---------调用后台人脸支付API发起支付");
wxFaceOrderVo.setOutTradeNo(getOutTradeNo());
micropayResult = this.toCreateWxOrder(authinfoResp, wxFaceOrderVo, wxFacePayResp0);
@@ -136,7 +139,7 @@ public class WxFacePayController {
@RequestMapping(value = "/initWxpayface", method = RequestMethod.POST)
public WxFacePayResp initWxpayface() throws JsonProcessingException, UnsupportedEncodingException, WxpayFaceSDKDll.DllRegistrationException {
// 构建请求参数的JSON字符串
WxFacePayReq wxFacePayReq = new WxFacePayReq("initWxpayface", "1", System.currentTimeMillis() / 1000, 3);
WxFacePayReq wxFacePayReq = new WxFacePayReq("initWxpayface", "1", System.currentTimeMillis() / 1000, 1);
WxFacePayResp wxFacePayResp = weChatPayFaceService.doWxPayIniMethod(wxFacePayReq);
log.info("[WxFacePayController][initWxpayface][132] [1、程序启动时初始化]{}", wxFacePayResp.toString());
return wxFacePayResp;
@@ -181,7 +184,6 @@ public class WxFacePayController {
public WxFacePayAuthinfoResp getWxpayfaceCode(@RequestBody WxFaceOrderVo wxFaceOrderVo, WxFacePayAuthinfoResp wxFacePayResp0) throws Exception {
//4、进行人脸识别getWxpayfaceCode获取支付凭证
String outTradeNo = getOutTradeNo();//获取流水号
// 构建请求参数的JSON字符串
WxFacePayReq wxFacePayReq = new WxFacePayReq("getWxpayfaceCode", "1", System.currentTimeMillis() / 1000);
wxFacePayReq.setAuthinfo(wxFacePayResp0.getAuthinfo())

View File

@@ -4,6 +4,8 @@ import com.dpkj.common.vo.Result;
import com.dpkj.modules.scanface.wx.dll.WxpayFaceSDKDll;
import com.dpkj.modules.scanface.wx.service.CallWxpayFaceService;
import com.dpkj.modules.scanface.wx.service.WeChatPayFaceService;
import com.dpkj.modules.scanface.wx.service.impl.CallWxpayFaceServiceImpl;
import com.dpkj.modules.scanface.wx.service.impl.WeChatPayFaceServiceImpl;
import com.dpkj.modules.scanface.wx.vo.WxFacePayAuthinfoResp;
import com.dpkj.modules.scanface.wx.vo.WxFacePayReq;
import com.dpkj.modules.scanface.wx.vo.WxFacePayResp;
@@ -13,11 +15,15 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.util.StringUtils;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.Provider;
import java.security.Security;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
/**

View File

@@ -7,6 +7,7 @@ import com.dpkj.modules.scanface.wx.vo.WxFacePayResp;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* @description: 调用微信刷脸方法

View File

@@ -45,7 +45,7 @@ public class CallWxpayFaceServiceImpl implements CallWxpayFaceService {
reqPointer.setString(0, reqJson);
//请求数据长度
int reqSize = reqPointer.getString(0).length();
log.info("000-----------调用微信刷脸DLL请求数据----------",reqPointer.getString(0));
System.out.println("-----------调用微信刷脸DLL请求数据----------"+reqPointer.getString(0));
//接收响应
long[] pRespBuf = new long[1];
@@ -56,20 +56,21 @@ public class CallWxpayFaceServiceImpl implements CallWxpayFaceService {
// 调用本地方法
WxpayFaceSDKDll.Dll dll = WxpayFaceSDKDll.instance();
int result = dll.wxpayCallFaceService(reqPointer.getString(0), reqSize, pRespBuf, respSize);
//使用C:\Windows\System32目录下 int result = WxpayFaceSDK.INSTANCE.wxpayCallFaceService(reqPointer.getString(0), reqSize, pRespBuf, respSize);
if (result == 0) {
Pointer pointer = new Pointer(pRespBuf[0]);
byte[] byteArray = pointer.getByteArray(0, respSize[0]);
resStr = new String(byteArray, StandardCharsets.UTF_8);
log.info("000-----------调用微信刷脸DLL请求结果: " , resStr);
System.out.println("-----------调用微信刷脸DLL请求结果: " + resStr);
dll.wxpayReleaseResponse(new String[2]);
//释放 C:\Windows\System32目录下 WxpayFaceSDK.INSTANCE.wxpayReleaseResponse(new String[2]);
} else {
Pointer pointer = new Pointer(pRespBuf[0]);
byte[] byteArray = pointer.getByteArray(0, respSize[0]);
resStr = new String(byteArray, StandardCharsets.UTF_8);
log.error("000-----------调用人脸DLL服务失败: " ,resStr);
System.err.println("-----------调用人脸服务失败: " +resStr);
}
return resStr;
}

View File

@@ -10,10 +10,13 @@ import com.dpkj.modules.scanface.wx.util.WXPayUtil;
import com.dpkj.modules.scanface.wx.util.WxRandomUtils;
import com.dpkj.modules.scanface.wx.util.XmlParserUtil;
import com.dpkj.modules.scanface.wx.util.XmlUtils;
import com.dpkj.modules.scanface.wx.vo.*;
import com.dpkj.modules.scanface.wx.vo.WxFacePayAuthinfoResp;
import com.dpkj.modules.scanface.wx.vo.WxFacePayMicroPayResp;
import com.dpkj.modules.scanface.wx.vo.WxFacePayOrderResp;
import com.dpkj.modules.scanface.wx.vo.WxFacePayReq;
import com.dpkj.modules.scanface.wx.vo.WxFacePayResp;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
@@ -24,10 +27,16 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @description: 调用微信刷脸方法

View File

@@ -3,12 +3,19 @@ package com.dpkj.modules.scanface.wx.util;
import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import javax.xml.bind.DatatypeConverter;
import java.io.StringReader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @description: 生成签名

View File

@@ -1,8 +1,6 @@
package com.dpkj.modules.scanface.wx.util;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;

View File

@@ -36,10 +36,8 @@ public class WxFaceOrderVo {
private String outTradeNo;
/**
* 用户支付金额 单位元
* 调用微信时需要转为分
* 用户支付金额
*/
private String totalAmount;
}

View File

@@ -1,30 +1,3 @@
server:
port: 5948
servlet:
context-path: /api
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
resource:
static-locations: classpath:/static/,classpath:/public/
logging:
level:
com.dpkj: debug
dpkj:
#后端项目访问地址 #https://yinyitong.yzqingyan.cn/ http://172.16.11.13:15946/ ttps://yinyitong.yzqingyan.cn
serverurl: http://localhost:5946/api/
@@ -32,6 +5,8 @@ dpkj:
chs:
# 医保机构编码
orgcode: H53082800070
# 医保读卡之后保存信息的文件名
file-name: outfile1191.txt
file:
# 文件保存地址
path: G:\Temp\img

View File

@@ -1,38 +1,12 @@
server:
port: 5946
servlet:
context-path: /api
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
resource:
static-locations: classpath:/static/,classpath:/public/
logging:
level:
com.dpkj: debug
dpkj:
#后端项目访问地址 #https://yinyitong.yzqingyan.cn/ http://172.16.11.13:15946/ ttps://yinyitong.yzqingyan.cn
serverurl: http://10.121.1.44/api/
serverurl: http://www.lczyyy.com/api/
# 医保配置
chs:
# 医保机构编码
orgcode: H53082800070
# 医保读卡之后保存信息的文件名
file-name: outfile1191.txt
file:
# 文件保存地址
path: D:\Project\Express\upload
@@ -54,40 +28,40 @@ dpkj:
#dll文件路径
dll-path: C:/opt/ant-abcp/bpaas_api.dll
#IOT 应用管理-appid
app-id: 2021005151604729
app-id: 2021005138656502
#IOT应用版本
app-version: 1.0.0.0
#签约商家的 PID以 2088 开头,企业主体
merchant-id: 2088170977486823
merchant-id: 2088641941653700
#商家机具终端编号,每台设备保持唯一
device-num: P060003750
#服务商的 PID
partner-id: 2088170977486823
partner-id: 2088641941653700
# 核心入参 serviceId
service-id: pay
#微信模块
wx:
configs: #中医院
- app-id: wxc12fa4977f66974d
configs: #清研家
- app-id: wxe8334dd2140bb0e1
# 公众号的appsecret
secret: a51dbcac25a73d7e4812a43cf550c5fc
secret: f83420d79cc6ecd1d7fe9684ac9cdfe4
# 接口配置里的Token值
token: DPKJYINYITONG
token: dpkjylwjvote
# 接口配置里的EncodingAESKey值
aes-key: yIBgBrHwRGjO2L3CLIE9hmnlf1FrXQQ7qJZVIg4r6Dx
mch-config: #商户信息 中医院
app-id: wxc12fa4977f66974d
secret: a51dbcac25a73d7e4812a43cf550c5fc
aes-key: go2uM3ASe2rEyeoNsZHoPCiKGgpku0Bi49P5IypdQWT
mch-config: #商户信息 清研家关联的商户:驿路万家-扬州清研软件科技
app-id: wxe8334dd2140bb0e1
secret: f83420d79cc6ecd1d7fe9684ac9cdfe4
#调用接口所需service_id
service-id: service_id
#商户号
mch-id: 1603658732
mch-id: 1557642321
#商户秘钥
mch-key: lczyywxc12fa4977f66974dyytzz1234
mch-key: yndpkj15288216506YndpkjKsjytZx12
#报文解密 APIv3密钥
v3-key: lczyywxc12fa4977f66974dyytzz1234
v3-key: yndpkj15288216506YndpkjKsjytZx12
#微信: 商户APIv2密钥
key-api: lczyywxc12fa4977f66974dyytzz1234
key-api: yndpkj15288216506YndpkjKsjytZx12
#p12证书的位置可以指定绝对路径也可以指定类路径以classpath;开头)
key-path: classpath:test\apiclient_cert.p12
private-key-path: classpath:test\apiclient_key.pem
@@ -105,9 +79,9 @@ dpkj:
url:
# 后端接口地址
# server: https://102760424tfyw.vicp.fun/api
server: ${dpkj.url.server-url}
server: ${dpkj.server-url}
# h5地址
h5: ${dpkj.url.h5-url}
h5: ${dpkj.h5-url}
# 身份证读取等待时间

View File

@@ -12,7 +12,7 @@ spring:
active: pro
server:
port: 5948 #5946
port: 5946
servlet:
context-path: /api
tomcat:

View File

@@ -29,9 +29,9 @@
</appender>
<!-- 生成 error html格式日志开始 -->
<!--<appender name="HTML" class="ch.qos.logback.core.FileAppender">
<appender name="HTML" class="ch.qos.logback.core.FileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
&lt;!&ndash;设置日志级别,过滤掉info日志,只输入error日志&ndash;&gt;
<!--设置日志级别,过滤掉info日志,只输入error日志-->
<level>ERROR</level>
</filter>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
@@ -40,15 +40,15 @@
</layout>
</encoder>
<file>${LOG_HOME}/error-log.html</file>
</appender>-->
</appender>
<!-- 生成 error html格式日志结束 -->
<!-- 每天生成一个html格式的日志开始 -->
<!-- <appender name="FILE_HTML" class="ch.qos.logback.core.rolling.RollingFileAppender">
<appender name="FILE_HTML" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
&lt;!&ndash;日志文件输出的文件名 &ndash;&gt;
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.html</FileNamePattern>
&lt;!&ndash;日志文件保留天数 &ndash;&gt;
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<MaxFileSize>10MB</MaxFileSize>
</rollingPolicy>
@@ -57,7 +57,7 @@
<pattern>%p%d%msg%M%F{32}%L</pattern>
</layout>
</encoder>
</appender>-->
</appender>
<!-- 每天生成一个html格式的日志结束 -->
<!--myibatis log configure -->
@@ -70,8 +70,8 @@
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
<!-- <appender-ref ref="HTML"/>-->
<!-- <appender-ref ref="FILE_HTML"/>-->
<appender-ref ref="HTML"/>
<appender-ref ref="FILE_HTML"/>
</root>
</configuration>

View File

@@ -70,10 +70,10 @@
</table>
</div>
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 20px;margin-right: 20px;font-size: 29px;word-break: break-all;">
<span>温馨提示:请妥善保管好您的缴费凭条,如果对缴费存在疑问,请到人工窗口咨询</span>
<div style="margin-left: 20px;font-size: 29px;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 20px;font-size: 27px;">
<span>温馨提示:请取走缴费凭证,并妥善保管。<br/>如果对缴费存在疑问,请到人工窗口咨询</span>
</div>
</div>
</body>

View File

@@ -29,10 +29,10 @@
</div>
</div>
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 20px;margin-right: 20px;font-size: 29px;word-break: break-all;">
<span>温馨提示:请妥善保管好您的缴费凭条,如果对缴费存在疑问,请到人工窗口咨询</span>
<div style="margin-left: 20px;font-size: 29px;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 20px;font-size: 27px;">
<span>温馨提示:请取走缴费凭证,并妥善保管。<br/>如果对缴费存在疑问,请到人工窗口咨询</span>
</div>
</div>
</body>

View File

@@ -27,10 +27,10 @@
</div>
</div>
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 20px;margin-right: 20px;font-size: 29px;word-break: break-all;">
<span>温馨提示:请妥善保管好您的缴费凭条,如果对缴费存在疑问,请到人工窗口咨询</span>
<div style="margin-left: 20px;font-size: 29px;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 20px;font-size: 27px;">
<span>温馨提示:请取走缴费凭证,并妥善保管。<br/>如果对缴费存在疑问,请到人工窗口咨询</span>
</div>
</div>
</body>

View File

@@ -25,24 +25,22 @@
<div style="margin-left: 20px;">就诊科室:<span th:text="${department}"></span></div>
<div style="margin-left: 20px;">出诊级别:<span th:text="${visitLevel}"></span></div>
<div style="margin-left: 20px;">就诊医生:<span th:text="${doctor}"></span></div>
<div style="margin-left: 20px;">就诊时间:<span th:text="${treatTime}"></span></div>
<div style="margin-left: 20px;">&emsp;&emsp;序:<span th:text="${sequence}"></span></div>
<div style="margin-left: 20px;">&ensp;&ensp;<span th:text="${totalFee}"></span></div>
<div style="margin-left: 20px;">挂号时间<span th:text="${registerDate}"></span></div>
<div style="margin-left: 20px;">挂号日期<span th:text="${registerDate}"></span></div>
<div style="margin-left: 20px;">&ensp;&ensp;<span th:text="${totalFee}"></span>&thinsp;</div>
<div style="margin-left: 20px;">支付方式:<span th:text="${paymentMethod}"></span></div>
<div style="margin-left: 20px;">交易流水:<span th:text="${transactionNumber}"></span></div>
<div style="margin-left: 20px;">交易流水:<span style="font-size: 26px;"
th:text="${transactionNumber}"></span></div>
<div style="width:100%;text-align: center;">
<img th:src="${qrCodeBase64}"
alt="#"/>
</div>
</div>
<div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">终端编号:<span
th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;word-break: break-all;">打印时间:<span th:text="${printTime}"></span>
</div>
<div style="margin-left: 20px;margin-right: 20px;font-size: 29px;word-break: break-all;">
<span>温馨提示:请妥善保管好您的缴费凭条,如果对缴费存在疑问,请到人工窗口咨询。</span>
<div style="margin-left: 20px;font-size: 29px;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 20px;font-size: 29px;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 20px;font-size: 27px;">
<span>温馨提示:请取走挂号凭证,并妥善保管。<br/>如果对缴费存在疑问,请到人工窗口咨询!</span>
</div>
</div>
</body>