Compare commits

..

2 Commits

Author SHA1 Message Date
1634084aea 支付宝刷脸完善 2025-06-17 15:46:22 +08:00
5a411843b5 支付宝刷脸完善 2025-06-17 15:09:43 +08:00
6 changed files with 116 additions and 49 deletions

View File

@@ -26,7 +26,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/chs/hispay")
public class HispayController {
private final IHispayService hispayService;
private final IHispayService iHispayService;
/**
@@ -38,7 +38,7 @@ public class HispayController {
@PostMapping("findReadCode")
public Result<?> findReadCode() {
try {
JSONObject res = hispayService.readCode();
JSONObject res = iHispayService.readCode();
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
@@ -63,7 +63,7 @@ public class HispayController {
throw new RuntimeException("密码不可为空");
}
JSONObject res = hispayService.readCard(password);
JSONObject res = iHispayService.readCard(password);
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
@@ -84,7 +84,7 @@ public class HispayController {
public Result<?> chsCodeAsOutpatientBegin(@RequestBody @Validated OutpatientBeginModel data) {
try {
log.info("[HispayController][chsCodeAsOutpatientBegin][门诊缴费-预算-电子医保凭证] 参数:{}", data);
ResultData res = hispayService.chsCodeAsOutpatientBegin(data);
ResultData res = iHispayService.chsCodeAsOutpatientBegin(data);
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
@@ -105,7 +105,7 @@ public class HispayController {
public Result<?> chsCodeAsOutpatientFinal(@RequestBody @Validated OutpatientFinalModel data) {
try {
log.info("[HispayController][chsCodeAsOutpatientFinal][门诊缴费-结算-电子医保凭证] 参数:{}", data);
ResultData res = hispayService.chsCodeAsOutpatientFinal(data);
ResultData res = iHispayService.chsCodeAsOutpatientFinal(data);
return Result.ok("成功", res);
} catch (Exception e) {
e.printStackTrace();
@@ -114,5 +114,4 @@ public class HispayController {
}
}
}

View File

@@ -43,4 +43,5 @@ public interface IHispayService {
*/
ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data);
}

View File

@@ -7,19 +7,20 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.config.ChsConfig;
import com.dpkj.common.config.HisConfig;
import com.dpkj.common.utils.IDGenerator;
import com.dpkj.common.vo.ResultData;
import com.dpkj.modules.chs.service.IHispayService;
import com.dpkj.modules.chs.vo.OutpatientBeginModel;
import com.dpkj.modules.chs.vo.OutpatientFinalModel;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import lombok.AllArgsConstructor;
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;
@@ -30,21 +31,11 @@ import java.util.Map;
*/
@Slf4j
@Service
// @AllArgsConstructor
@AllArgsConstructor
public class HispayServiceImpl implements IHispayService {
@Autowired
private HisConfig hisConfig;
@Autowired
private ChsConfig chsConfig;
// COM对象
private static ActiveXComponent dispatch;
@PostConstruct
public void postConstruct() {
dispatch = instanceActive();
}
private final HisConfig hisConfig;
private final ChsConfig chsConfig;
/**
* 获取HIS医保实例
@@ -52,13 +43,14 @@ public class HispayServiceImpl implements IHispayService {
* @return com.jacob.activeX.ActiveXComponent
* @author 萧道子 2025/5/21
*/
private static ActiveXComponent instanceActive() {
private ActiveXComponent instanceActive() {
try {
// 初始化
// ComThread.InitSTA(); //容易导致线程发生阻塞
ActiveXComponent activeXComponent = new ActiveXComponent("PayClient.clsPayClient");
ComThread.InitSTA();
// 获取COM对象
ActiveXComponent active = new ActiveXComponent("PayClient.clsPayClient");
log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载成功");
return activeXComponent;
return active;
} catch (UnsatisfiedLinkError e) {
log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载失败:{}", e.getMessage());
throw new RuntimeException("HIS医保COM库加载失败" + e.getMessage(), e);
@@ -73,7 +65,7 @@ public class HispayServiceImpl implements IHispayService {
* @author 萧道子 2025/5/21
*/
private void releaseActive() {
// ComThread.Release(); //容易导致线程发生阻塞
ComThread.Release();
}
/**
@@ -86,9 +78,9 @@ public class HispayServiceImpl implements IHispayService {
*/
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("timestamp", DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")); // 请求发送时间
put("requestid", IDGenerator.getSnowflakeIdToStr()); // 唯一请求id
put("operid", hisConfig.getOperationId()); // 调用者代码
put("password", password); // 密码
put("params", params);
}};
@@ -128,6 +120,9 @@ public class HispayServiceImpl implements IHispayService {
@Override
public JSONObject readCode() {
// 加载资源
Dispatch dispatch = instanceActive();
/** 1、组装参数 */
JSONObject val = new JSONObject()
.fluentPut("cardtype", "9") // 1.就诊卡2.医保卡5.门诊号6.患者姓名和电话号码8.电子健康码/卡9.医保电子凭证
@@ -145,6 +140,8 @@ public class HispayServiceImpl implements IHispayService {
String resStr = vres.getStringRef();
log.info("[HispayServiceImpl][readCode][医保读卡-电子凭证] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
/** 3、处理读卡结果 */
JSONObject result = verifyResult(resStr);
@@ -157,6 +154,8 @@ public class HispayServiceImpl implements IHispayService {
@Override
public JSONObject readCard(String password) {
// 加载资源
Dispatch dispatch = instanceActive();
/** 1、组装参数 */
JSONObject val = new JSONObject()
@@ -175,6 +174,9 @@ public class HispayServiceImpl implements IHispayService {
String resStr = vres.getStringRef();
log.info("[HispayServiceImpl][readCard][医保读卡-医保卡] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
/** 3、处理读卡结果 */
JSONObject result = verifyResult(resStr);
if (!result.containsKey("item")) {
@@ -185,7 +187,67 @@ public class HispayServiceImpl implements IHispayService {
}
// public JSONObject getPatientInfo_old(String type, String content) {
// Dispatch dispatch = instanceActive();
//
// /**
// * 1、删除保存HIS读卡内容的文件 避免读取到错误信息
// */
// // 获取HIS-CHS医保库路径
// String chsPath = System.getProperty("java.library.path");
// String filePath = chsPath + "/" + chsConfig.getFileName();
// // 删除文件
// FileUtil.del(FileUtil.file(filePath));
//
// /**
// * 2、组装参数
// */
// JSONObject val = new JSONObject()
// .fluentPut("cardtype", type) // 1.就诊卡2.医保卡5.门诊号6.患者姓名和电话号码8.电子健康码/卡9.医保电子凭证
// .fluentPut("cardno", "") // 患者就诊卡号
// .fluentPut("sfzh", "") // 身份证号
// .fluentPut("hzxm", "") // 患者姓名
// .fluentPut("phone", ""); // 患者电话号码
// String params = processParameters(val, content);
// log.info("[HispayServiceImpl][getPatientInfo][医保读卡] 接口入参:{}", params);
//
// /**
// * 3、调用COM函数
// */
// Variant rest = new Variant();
// Variant call = Dispatch.call(dispatch, "fRun", "BMZXX010", params, rest);
// log.info("[HispayServiceImpl][getPatientInfo][医保读卡] call返回值{}", call);
//
// // 释放资源
// releaseActive();
//
// /**
// * 4、处理读卡结果
// */
// // COM函数调用之后会生成新的文件 需要判断
// File file = FileUtil.file(filePath);
// if (!file.exists()) {
// throw new RuntimeException("读卡失败:数据未读取");
// }
//
// // 获取读卡结果
// FileReader fileReader = new FileReader(file, "GBK");
// String data = fileReader.readString();
//
// JSONObject result;
// try {
// result = JSONObject.parseObject(data);
// log.info("[HispayServiceImpl][getPatientInfo][医保读卡] 读卡值:{}", result);
// } catch (Exception e) {
// throw new RuntimeException("读卡失败:" + data);
// }
// return result;
// }
private ResultData outpatientBudget(OutpatientBeginModel data) {
// 加载资源
ActiveXComponent dispatch = instanceActive();
/** 1、组装参数 */
JSONObject val = new JSONObject()
@@ -207,6 +269,8 @@ public class HispayServiceImpl implements IHispayService {
String resStr = resVariant.getStringRef();
log.info("[HispayServiceImpl][outpatientBudget][门诊缴费-预算] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
/** 3、处理结果 */
JSONObject result = verifyResult(resStr);
@@ -233,19 +297,16 @@ public class HispayServiceImpl implements IHispayService {
@Override
public ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data) {
// 加载资源
ActiveXComponent dispatch = instanceActive();
/** 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", "");
JSONObject val = (JSONObject) JSON.toJSON(data);
String params = processParameters(val, null);
log.info("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] 接口入参:{}", params);
String requestTime = DateUtil.now();
/** 2、调用COM函数 */
Variant resVariant = new Variant("", true);
Variant call = Dispatch.call(dispatch, "fRun", "BMZJF002", params, resVariant);
@@ -254,6 +315,13 @@ public class HispayServiceImpl implements IHispayService {
String resStr = resVariant.getStringRef();
log.info("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
// TODO BEGIN 萧道子 2025/6/10 : 模拟参数
// String resStr = "<response><resultCode>0</resultCode><resultMessage/><result><sjh>123456789</sjh><sfrq>2025-06-10 10:23:14</sfrq><bz/><pyckjh/><fyckjh/><yflshjh/><ybcc/></result></response>";
// TODO END 萧道子 2025/6/10 : 模拟参数
/** 3、处理结果 */
JSONObject result = verifyResult(resStr);

View File

@@ -43,7 +43,5 @@ public class OutpatientFinalModel implements Serializable {
/**
* 支付时间
*/
// @NotEmpty(message = "支付时间不可为空!")
private String paytime;
}

View File

@@ -69,9 +69,11 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
String json = params.toJSONString();
String service_code = AliFaceConstants.SMILEVERIFYNIN_V1; //调用的组件编码:初始化
Result<Object> startServiceIniResult = this.startServiceIni(json, service_code);
log.info("[AliScanFaceServiceImpl][aliFacePay][72][调用ABCP调用刷脸的结果] {}", startServiceIniResult.toString());
if (startServiceIniResult.isSuccess()) {
Map<String, String> res = (Map<String, String>) startServiceIniResult.getResult();
String ftoken = res.get("ftoken");
log.info("[AliScanFaceServiceImpl][aliFacePay][76][调用ABCP调用刷脸的结果的ftoken] {}", ftoken.toString());
/**
* 2、调用后端的支付宝统一收单交易支付接口、存入hisPay
@@ -80,12 +82,15 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
JSONObject serverParams = (JSONObject) JSON.toJSON(aliOrderVo);
String url = serverUrl + "openapi/aliPayOrderApi/createOrder";
log.info("[AliScanFaceServiceImpl][aliFacePay][85][调用后端的支付宝统一收单交易支付接口路径] {}", serverUrl);
log.info("[AliScanFaceServiceImpl][aliFacePay][85][调用后端的支付宝统一收单交易支付接口参数] {}", serverParams.toJSONString());
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 {
@@ -186,7 +191,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
AbcpInvoke.CallbackRsp callbackRsp = new AbcpInvoke.CallbackRsp() {
@Override
public void OnProcess(int code, String subCode, String subMsg, String result) {
log.info("[AliScanFaceServiceImpl][OnProcess][123][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result);
log.info("[AliScanFaceServiceImpl][OnProcess][189][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result);
try {
processCode.set(code);
processResult.set(result);
@@ -197,7 +202,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
@Override
public void OnFinish(int code, String subCode, String subMsg, String result) {
log.info("[AliScanFaceServiceImpl][OnFinish][128][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result);
log.info("[AliScanFaceServiceImpl][OnFinish][200][ABCP服务调用 刷脸初始化服务,获取ftoken:][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result);
/**Demo示例记录
* [service_code:BPaaSSmileVerifyNonInitV1][code:1000][subCode:E00000][subMsg:SUCCESS][result:{"code":1000,"subCode":"OK_SUCCESS","subMessage":"SUCCESS","barCode":"281215320962898068","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","alipayUid":"2088812449506047","accountList":"[\"104***@qq.com\"]","authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","result":{"accountList":["104***@qq.com"],"alipayUid":"2088812449506047","allowRetry":false,"authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","barCode":"281215320962898068","certName":"您好,*雪","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","type":"selectUid"},"easterEgg":false,"zolozConfig":{"installAngle":90},"serviceId":"pay","traceId":"2444-44-1745802328","callStartTimeMs":1745802328114,"localTime":"2025-04-28-09-05-41-791"}]
@@ -218,10 +223,12 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
// 等待process回调完成设置超时避免死锁
boolean awaitSuccess = latch.await(10, TimeUnit.SECONDS);
if (!awaitSuccess) {
log.info("[AliScanFaceServiceImpl][startServiceIni][221][service_code:{}][ABCP调用刷脸:等待process回调超时]", service_code);
return Result.error("等待process回调超时");
} else {
if (processCode.get() == 0) {
JSONObject jsonObject = JSONObject.parseObject(processResult.get());
log.info("[AliScanFaceServiceImpl][startServiceIni][225][service_code:{}][ABCP调用刷脸-等待process回调完成结果] {}", service_code, jsonObject.toString());
if (jsonObject.containsKey("traceId")) {
res.put("traceId", jsonObject.getString("traceId"));
} else {
@@ -239,6 +246,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
} else {
if (finishCode.get() == 1000) {
JSONObject jsonObject = JSONObject.parseObject(finishResult.get());
log.info("[AliScanFaceServiceImpl][startServiceIni][244][service_code:{}] [ABCP调用刷脸-等待finish回调完成结果]{}", service_code, jsonObject.toString());
if (jsonObject.containsKey("ftoken")) {
res.put("ftoken", jsonObject.getString("ftoken"));//ftoken参数的有效期为2分钟
res.put("barCode", jsonObject.getString("barCode"));
@@ -255,6 +263,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
return finishResultRef.get();
} catch (Exception e) {
e.printStackTrace();
log.info("[AliScanFaceServiceImpl][startServiceIni][261][ABCP调用刷脸初始化服务失败] {}", e.getMessage());
return Result.error("ABCP调用刷脸初始化服务失败" + e.getMessage());
}
}

View File

@@ -40,14 +40,6 @@
<span style="margin-right: 25px;">费用总额:<span th:text="${totalFee}"></span></span>
<span>个人支付:<span th:text="${personalPayment}"></span></span>
</div>
<div style="margin-top: 10px;word-break: break-all;" th:if="${chs==1}">
<span style="margin-right: 25px;">医保统筹基金:<span th:text="${ybtcjj}"></span></span>
<span>个人医保账户:<span th:text="${ybgrzh}"></span></span>
</div>
<div style="margin-top: 10px;word-break: break-all;" th:if="${chs==1}">
<span style="margin-right: 25px;">医院优惠金额:<span th:text="${yyyh}"></span></span>
<span>医院账户支付:<span th:text="${yyzh}"></span></span>
</div>
<div style="margin-top: 10px;word-break: break-all;">
<span>实收金额:</span><span
th:text="${actualReceiptAmount}"></span></div>