1、调整:盒子支付查询时间调整、新增耗时统计下单调用时长统计。

2、新增:新增编码转条码base64的功能。
3、新增:小程序患者id加密后替换服务端加密的患者id和证件号的接口。
4、优化:认证参数位置调整,防止state参数过长在调试工具无法使用的问题
debug
王绍全 3 weeks ago
parent 77dc7f700a
commit 683d29bae8
  1. 45
      src/main/java/com/ynxbd/common/action/ApiAction.java
  2. 7
      src/main/java/com/ynxbd/common/action/HealthCodeAction.java
  3. 6
      src/main/java/com/ynxbd/common/action/PatientAction.java
  4. 9
      src/main/java/com/ynxbd/common/action/pay/PayAction.java
  5. 7
      src/main/java/com/ynxbd/common/action/test/TestAction.java
  6. 14
      src/main/java/com/ynxbd/common/config/db/DataBase.java
  7. 62
      src/main/java/com/ynxbd/common/dao/PatientDao.java
  8. 23
      src/main/java/com/ynxbd/common/dao/his/HisPatientDao.java
  9. 28
      src/main/java/com/ynxbd/common/helper/common/AesMiniHelper.java
  10. 56
      src/main/java/com/ynxbd/common/helper/common/BarcodeHelper.java
  11. 9
      src/main/java/com/ynxbd/common/helper/common/URLHelper.java
  12. 3
      src/main/java/com/ynxbd/common/helper/his/HisEnum.java
  13. 106
      src/main/java/com/ynxbd/common/service/PatientService.java
  14. 20
      src/main/java/com/ynxbd/wx/config/WeChatConfig.java
  15. 4
      src/main/java/com/ynxbd/wx/servlet/QServlet.java
  16. 2
      src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java
  17. 63
      src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java
  18. 23
      src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java
  19. 2
      src/main/resources/webservice.properties

@ -170,16 +170,35 @@ public class ApiAction extends BaseAction {
return Result.success(base);
}
@Action("getEnPatientId")
public Result getEnPatientId(String patientId) {
if (patientId == null) {
@Action("getEnData")
public Result getEnData(String callNo, String miniCardNo, String miniPatientId) {
if (!"xbd".equals(callNo)) {
return Result.error(ResultEnum.PARAM_CALL_NO_NOT_FOUND);
}
if (miniPatientId == null) {
return Result.error(ResultEnum.PARAM_IS_DEFECT);
}
patientId = AesWxHelper.encode(patientId);
for (int i = 0; i < 3; i++) {
patientId = Base64.getEncoder().encodeToString(patientId.getBytes());
String patientId = AesMiniHelper.decode(miniPatientId);
if (patientId == null) {
return Result.error(ResultEnum.PARAM_IS_INVALID);
}
patientId = Base64Helper.encode(AesWxHelper.encode(patientId));
String cardNo = null;
if (!ObjectUtils.isEmpty(miniCardNo)) {
cardNo = AesMiniHelper.decode(miniCardNo);
if (ObjectUtils.isEmpty(cardNo)) {
return Result.error(ResultEnum.PARAM_IS_INVALID);
}
cardNo = Base64Helper.encode(AesWxHelper.encode(cardNo));
}
return Result.success(patientId);
Map<String, Object> map = new HashMap<>();
map.put("enCardNo", cardNo);
map.put("enPatientId", patientId);
return Result.success(map);
}
/**
@ -216,6 +235,18 @@ public class ApiAction extends BaseAction {
return Result.success(VersionHelper.getAppVersion());
}
@Action("barcode")
public Result barcode(String callNo, String code, Integer width, Integer height) {
if (callNo == null || code == null || width == null || height == null) {
return Result.error(ResultEnum.PARAM_IS_DEFECT);
}
if (!"xbd".equals(callNo)) {
return Result.error(ResultEnum.PARAM_IS_INVALID);
}
return Result.success(BarcodeHelper.generateBarcodeBase64(code, width, height));
}
/**
* 第三方使用勿动

@ -323,6 +323,7 @@ public class HealthCodeAction extends BaseAction {
* [升级绑定]-->已在HIS绑定-->注册健康卡
*
* @param wechatCode wechatCode
* @param id id
* @param idCardNo idCardNo
* @param cardType cardType
* @param openid openid
@ -333,8 +334,8 @@ public class HealthCodeAction extends BaseAction {
* @param address address
*/
@Action("upBind")
public Result upBind(String wechatCode, String idCardNo, String cardType, String openid, String tel, String name, String nation, String patientId, String address) {
log.info("[电子健康卡]升级绑定 name={}, address={}, nation={}, patientId={}, tel={}, idType={}, wechatCode={}", name, address, nation, patientId, tel, cardType, wechatCode);
public Result upBind(String wechatCode, Integer id, @AesDecode String idCardNo, @AesDecode String patientId, String cardType, String openid, String tel, String name, String nation, String address) {
log.info("[电子健康卡]升级绑定 id={}, name={}, address={}, nation={}, patientId={}, tel={}, idType={}, wechatCode={}", id, name, address, nation, patientId, tel, cardType, wechatCode);
if (wechatCode == null || openid == null || patientId == null || name == null || idCardNo == null || tel == null || address == null || nation == null) {
return Result.error(ResultEnum.PARAM_IS_DEFECT);
}
@ -384,7 +385,7 @@ public class HealthCodeAction extends BaseAction {
bindInfo.setTel(tel);
bindInfo.setAddress(address);
boolean isUpdate = new PatientDao().updateInfo(bindInfo);
boolean isUpdate = new PatientDao().updateInfo(bindInfo, id);
if (isUpdate) {
Cache<String, User> cache = WxCacheHelper.getUserCacheManager();
cache.remove(openid);

@ -390,4 +390,10 @@ public class PatientAction extends BaseAction {
new PatientService().wh_gmc_patient_ids();
return Result.success();
}
@Action("queryGMCId")
public Result queryGMCId(@AesDecode String hisPatientId) {
String gmcPatientId = new HisPatientDao().getGMCPatientId(hisPatientId);
return Result.success(gmcPatientId);
}
}

@ -209,6 +209,7 @@ public class PayAction extends BaseAction {
*/
@Action("payMicro")
public Result payMicro(String authCode, String callNo, String treatNum, String patientId, String title, String operateUser, BigDecimal totalFee, String invoiceTransNo, String regDate) {
long begTime = System.currentTimeMillis();
Result result = PayService.isPaymentPermittedByTime();
if (result != null) {
return result;
@ -260,6 +261,10 @@ public class PayAction extends BaseAction {
boolean isSuccess = PayService.updateMicroOrderState(pEnum, outTradeNo, orderMicro.getBankTransNo(), orderMicro.getOpenid());
long endTime = System.currentTimeMillis(); // 结束时间
String takeTime = (endTime - begTime) + "ms"; // 耗时
log.info("[扫码盒子]支付-共耗时:[{}]", takeTime);
return isSuccess ? Result.success(outTradeNo)
: Result.error(ResultEnum.ERROR, outTradeNo);
}
@ -371,8 +376,8 @@ public class PayAction extends BaseAction {
for (int i = 0; i <= 4; i++) {
try {
if (i != 0) {
log.info("[盒子支付]订单查询 outTradeNo={} [{}]", outTradeNo, i);
Thread.sleep(2000 + (i * 1500)); // 0 | 3.5 | 5 | 6.5 | 7 = 22s
log.info("[盒子支付]订单查询[第{}]次 outTradeNo={}", i, outTradeNo);
Thread.sleep(3000); // 15s
}
order = PayService.queryOrderByOutTradeNo(outTradeNo, null);
if (order.isSuccess()) {

@ -111,6 +111,13 @@ public class TestAction extends BaseAction {
return Result.success();
}
@Action("r_test")
public Result r_test() throws ServiceException {
String url = WeChatConfig.getHttpsBaseURL() + "ali_qrcode" + "?p=123";
System.out.println(url);
System.out.println();
return Result.redirect( "/wx/test02/log_test");
}
// @Action("lock")
// public String lock() {

@ -548,11 +548,11 @@ public class DataBase {
*/
public static int updateBatch(String tableName, Map<String, Object> setMap, Map<String, List<Map<String, Object>>> setByCaseList, Map<String, Object> whereMap, List<String> ids) {
StringBuilder sb = new StringBuilder();
if (tableName == null || "".equals(tableName)) {
if (tableName == null || ObjectUtils.isEmpty(tableName)) {
return 0;
}
if (setByCaseList == null || setByCaseList.size() == 0 || ids == null || ids.size() == 0) {
if (setByCaseList == null || setByCaseList.isEmpty() || ids == null || ids.isEmpty()) {
return 0;
}
@ -566,7 +566,7 @@ public class DataBase {
value = "'" + value + "'";
}
sb.append(entry.getKey()).append("=").append(value);
if ((mapIndex + 1) != setMap.entrySet().size()) {
if ((mapIndex + 1) != setMap.size()) {
sb.append(",");
}
mapIndex++;
@ -574,7 +574,7 @@ public class DataBase {
}
if (setMap != null && setMap.entrySet().size() != 0) {
if (setMap != null && !setMap.isEmpty()) {
sb.append(",");
}
@ -586,7 +586,7 @@ public class DataBase {
key = entry.getKey();
valMapList = entry.getValue();
if (ObjectUtils.isEmpty(key) || valMapList == null || valMapList.size() == 0) {
if (ObjectUtils.isEmpty(key) || valMapList == null || valMapList.isEmpty()) {
continue;
}
sb.append(key).append("= case id");
@ -604,7 +604,7 @@ public class DataBase {
sb.append(" end ");
}
}
if ((mapIndex + 1) != setByCaseList.entrySet().size()) {
if ((mapIndex + 1) != setByCaseList.size()) {
sb.append(",");
}
mapIndex++;
@ -633,7 +633,7 @@ public class DataBase {
sb.append(")");
String sql = sb.toString();
log.info("sql={}", sql);
if ("".equals(sb.toString())) {
if (ObjectUtils.isEmpty(sb.toString())) {
return 0;
}
return update(sql, null);

@ -92,21 +92,6 @@ public class PatientDao {
});
}
/**
* 根据身份证查询患者
*
* @param openid openid
* @param idCardNo 身份证号
* @return 患者信息
*/
public Patient selectByIdCardNo(String openid, String idCardNo) {
String sql = "select * from patientBase where openid= ? and idCardNo= ?";
List<Patient> resultList = DataBase.select(sql, Patient.class, ps -> {
ps.setString(1, openid);
ps.setString(2, idCardNo);
});
return !resultList.isEmpty() ? resultList.get(0) : null;
}
/**
* 根据身份证查询患者
@ -180,6 +165,29 @@ public class PatientDao {
}) > 0;
}
/**
* 根据身份证查询患者
*
* @param openid openid
* @param idCardNo 身份证号
* @return 患者信息
*/
public Patient selectByIdCardNo(String openid, String idCardNo) {
String sql = "select * from patientBase where openid= ? and idCardNo= ?";
List<Patient> resultList = DataBase.select(sql, Patient.class, ps -> {
ps.setString(1, openid);
ps.setString(2, idCardNo);
});
return !resultList.isEmpty() ? resultList.get(0) : null;
}
public List<Patient> selectByOpenIdAndCardNo(String openid, String idCardNo) {
String sql = "select * from patientBase where openid= ? and idCardNo= ?";
return DataBase.select(sql, Patient.class, ps -> {
ps.setString(1, openid);
ps.setString(2, idCardNo);
});
}
/**
* 更新用户信息
@ -187,11 +195,14 @@ public class PatientDao {
* @param bindInfo 绑定信息
* @return 是否成功
*/
public boolean updateInfo(Patient bindInfo) {
public boolean updateInfo(Patient bindInfo, Integer id) {
if (id == null) {
return false;
}
String sql = "update patientBase set deletedState=0, healthCardId=?, name=?, nation=?, tel=?, address=?, uuid=?, areaCode=?, areaAddress=?, patientId=?, hisPatientId=?, gmcBindState=?, " +
" uniqueId=if(uniqueId is null or uniqueId = '', ?, uniqueId), " +
" gmcUniqueId=if(gmcUniqueId is null or gmcUniqueId = '', ?, gmcUniqueId) " +
" where openid=? and idCardNo=?";
" where id=? and openid=? and idCardNo=?";
bindInfo.setGmcBindState(WeChatConfig.IS_ENABLE_GMC ? 1 : 0);
bindInfo.setHisPatientId(WeChatConfig.IS_ENABLE_GMC ? null : bindInfo.getPatientId());
@ -211,8 +222,9 @@ public class PatientDao {
ps.setString(12, CodeHelper.get32UUID());
ps.setString(13, bindInfo.getGmcUniqueId());
// 条件
ps.setString(14, bindInfo.getOpenid());
ps.setString(15, bindInfo.getIdCardNo());
ps.setInt(14, id);
ps.setString(15, bindInfo.getOpenid());
ps.setString(16, bindInfo.getIdCardNo());
}) > 0;
}
@ -451,29 +463,27 @@ public class PatientDao {
log.warn("[医共体]功能未开启-禁止查询不是医共体的用户信息");
return new ArrayList<>();
}
String sql = "select * from patientBase where (gmcBindState is null or gmcBindState != 1)";
String sql = "select * from patientBase where (hisPatientId is null or hisPatientId = '')";
return DataBase.select(sql, Patient.class, null);
}
public boolean updateGmcInfo(Integer id, String cardNo, String cardType, String gmcPatientId, String hisPatientId) {
if (ObjectUtils.isEmpty(cardNo) && HCardTypeEnum.NO_CARD.WX_CODE.equals(cardType)) { // 无证绑定->标记为已删除
String sql = "update patientBase set deletedState= 1 where id=? and cardType=?";
public boolean updateGmcInfo(boolean hasCard, Integer id, String gmcPatientId, String hisPatientId) {
if (!hasCard) { // 无证绑定->标记为已删除
String sql = "update patientBase set deletedState= 1 where id=?";
return DataBase.update(sql, ps -> {
ps.setLong(1, id);
ps.setString(2, HCardTypeEnum.NO_CARD.WX_CODE);
}) > 0;
}
if (ObjectUtils.isEmpty(gmcPatientId)) {
return false;
}
String sql = "update patientBase set gmcBindState= 1, patientId=?, hisPatientId=? where id=? and idCardNo= ?";
String sql = "update patientBase set gmcBindState= 1, patientId=?, hisPatientId=? where id=?";
return DataBase.update(sql, ps -> {
ps.setString(1, gmcPatientId);
ps.setString(2, hisPatientId);
// 条件
ps.setLong(3, id);
ps.setString(4, cardNo);
}) > 0;
}
}

@ -159,6 +159,29 @@ public class HisPatientDao {
}
/**
* [医共体]查询医共体患者id
*
* @return 患者
*/
public String getGMCPatientId(String hisPatientId) {
if (ObjectUtils.isEmpty(hisPatientId)) {
return null;
}
Map<String, Object> params = new HashMap<>();
params.put("PatientID", hisPatientId);
JsonResult jsonResult = HisHelper.getJsonResult(HisEnum.AP_Query_GMC_Patient, params);
if (!jsonResult.success()) {
return null;
}
String gmcId = jsonResult.getDataMapString("Empi_Id");
if (ObjectUtils.isEmpty(gmcId)) {
return null;
}
return gmcId;
}
/**
* 修改患者信息
*

@ -0,0 +1,28 @@
package com.ynxbd.common.helper.common;
import org.apache.commons.lang3.ObjectUtils;
import java.math.BigDecimal;
public class AesMiniHelper extends AesHelper {
private static final String KEY = "miniappaesencode";
private static final String IV = "ynxbdminiappjsfl";
public static String encode(String data) {
return encryptHex(data, KEY, IV);
}
/**
* 解密
*/
public static String decode(String enData) {
if (ObjectUtils.isEmpty(enData)) return null;
return decryptHex(enData, KEY, IV);
}
public static void main(String[] args) {
System.out.println(encode("11105244"));
System.out.println(decode("726D304427D544FC660136A613D4E6A4"));
}
}

@ -0,0 +1,56 @@
package com.ynxbd.common.helper.common;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.google.zxing.BarcodeFormat;
import org.apache.commons.io.output.ByteArrayOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Base64;
public class BarcodeHelper {
/**
* 生成条形码 Base64无前缀
*
* @param content 内容CODE_128支持字母+数字
* @param width
* @param height
* @return base64异常返回null
*/
public static String generateBarcodeBase64(String content, int width, int height) {
if (content == null) {
return null;
}
try {
// 1. 配置
QrConfig config = new QrConfig(width, height);
config.setMargin(1); // 白边
config.setForeColor(Color.BLACK); // 黑
config.setBackColor(Color.WHITE); // 白
// 2. 生成条形码(指定CODE_128)
BufferedImage image = QrCodeUtil.generate(
content,
BarcodeFormat.CODE_128,
config
);
// 3. 转Base64
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
ImgUtil.write(image, "PNG", out);
// data:image/png;base64,
return Base64.getEncoder().encodeToString(out.toByteArray());
}
} catch (Exception e) {
return null;
}
}
public static void main(String[] args) throws Exception {
String base64 = generateBarcodeBase64("1234567890", 300, 80);
System.out.println("data:image/png;base64," + base64);
}
}

@ -73,6 +73,14 @@ public class URLHelper {
return url;
}
public static String encodeURL(String param, boolean isReturnNull) {
param = encodeURL(param);
if (param == null) {
return isReturnNull ? null : "";
}
return param;
}
public static String encodeURL(String param) {
try {
return URLEncoder.encode(param, "UTF-8");
@ -82,6 +90,7 @@ public class URLHelper {
return null;
}
public static String decodeURL(String param) {
try {
return URLDecoder.decode(param, "UTF-8");

@ -6,6 +6,7 @@ public enum HisEnum {
AP_Query_Patient("[患者]获取用户绑定信息", "1001", "AP_Query_Patient", true),
AP_Binding_Card("[患者]身份证绑定", "1002", "AP_Binding_Card", true),
AP_UnBinding_Card("[患者]身份证解绑", "1003", "AP_UnBinding_Card", true),
AP_Query_GMC_Patient("[患者]医共体ID查询", "1015", "UniversalInterface", true),
Medical_Insurance_Bill("[医保]查询患者医保结算清单", "1008", "UniversalInterface", true),
@ -105,7 +106,7 @@ public enum HisEnum {
// 在线签到
AP_Query_SignIn("[在线签到]查询预约待签到记录","7007","AP_Query_SignIn",true),
AP_SignIN("[在线签到]执行预约签到","7008","AP_SignIn",true),
AP_Query_Line_SignIn("[在线签到]查询已挂号未签到记录","7009","AP_Query_LineSignIn",true),
AP_Query_Line_SignIn("[在线签到]查询已挂号未签到记录","7009","AP_Query_LineSignIn",false),
AP_Line_SignIN("[在线签到]执行挂号患者签到","7010","AP_LineSignIn",true),
// 自助开单

@ -20,6 +20,7 @@ import org.apache.commons.lang3.ObjectUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
/**
* 患者业务层
@ -97,6 +98,25 @@ public class PatientService {
return bind(request, isMyself, isAreaCode, bindInfo);
}
private void updateBind(List<Patient> patients, Patient bindInfo, String healthCardId) throws ServiceException {
for (Patient patientItem : patients) {
String dbPatientId = patientItem.getPatientId();
if (healthCardId != null && new HCodeService().bindCardRelation(false, dbPatientId, healthCardId) == null) { // 绑定患者和院内关系
log.info("[电子健康卡]绑定患者和医院关系失败");
}
String hcId = patientItem.getHealthCardId();
if (!ObjectUtils.isEmpty(hcId)) {
healthCardId = hcId;
}
if (!new PatientDao().updateInfo(bindInfo, patientItem.getId())) {
log.info("[患者]更新失败 patientId={}", dbPatientId);
throw new ServiceException(ResultEnum.PATIENT_UPDATE_ERROR);
}
}
}
/**
* [绑定]
*
@ -141,7 +161,6 @@ public class PatientService {
}
PatientDao patientDao = new PatientDao();
List<Patient> patients = patientDao.selectListByOpenid(openid);
if (patients.size() > 5) {
log.info("[患者]绑定患者数超过5人 openid={}", openid);
return Result.error(ResultEnum.PATIENT_BIND_EXCEEDS_5); // 绑定人数超过5人
@ -154,7 +173,7 @@ public class PatientService {
return Result.error(e);
}
if (hisPatient == null || hisPatient.getPatientId() == null) {
if (hisPatient == null || ObjectUtils.isEmpty(hisPatient.getPatientId())) {
return Result.error(ResultEnum.INTERFACE_HIS_INVOKE_ERROR); // HIS接口调用失败
}
@ -167,8 +186,9 @@ public class PatientService {
// bindInfo.setGmcHospId(gmcHospId);
// 判断是否已有数据
Patient patient = patientDao.selectByIdCardNo(openid, idCardNo);
if (patient == null) { // 数据库没有-->添加
try {
List<Patient> dbPatients = patientDao.selectByOpenIdAndCardNo(openid, idCardNo);
if (dbPatients.isEmpty()) { // 数据库没有-->添加
log.info("[用户身份绑定]添加 name={}, patientId={}", name, patientId);
bindInfo.setGmcBindState(1);
if (bindInfo.getEnUnionId() != null) {
@ -180,29 +200,24 @@ public class PatientService {
}
} else {
patientId = patient.getPatientId();
if (healthCardId != null && new HCodeService().bindCardRelation(false, patientId, healthCardId) == null) { // 绑定患者和院内关系
log.info("[电子健康卡]绑定患者和医院关系失败");
}
String hcId = patient.getHealthCardId();
if (!ObjectUtils.isEmpty(hcId)) {
healthCardId = hcId;
}
log.info("[患者]更新 isMyself={}, patientId={}, name={}, healthCardId={}", isMyself, patientId, name, healthCardId);
if (isMyself) {
if (!patientDao.updateMyself(bindInfo)) {
log.info("[患者]自身信息更新失败 patientId={}", patientId);
return Result.error(ResultEnum.DATA_UPDATE_ERROR);
return Result.error(ResultEnum.PATIENT_UPDATE_ERROR);
}
} else {
if (!patientDao.updateInfo(bindInfo)) {
log.info("[患者]更新失败 patientId={}", patientId);
return Result.error(ResultEnum.PATIENT_UPDATE_ERROR);
List<Patient> pIdEqualsPatients = dbPatients.stream().filter(o -> o.getPatientId().equals(hisPatient.getPatientId())).collect(Collectors.toList());
if (pIdEqualsPatients.isEmpty()) { // 患者ID相同的人数不为0
updateBind(dbPatients, bindInfo, healthCardId);
} else {
updateBind(pIdEqualsPatients, bindInfo, healthCardId);
}
}
}
} catch (Exception e) {
return Result.error(e);
}
WxCacheHelper.removeUser(openid);
Map<String, Object> map = new HashMap<>();
@ -211,6 +226,10 @@ public class PatientService {
return Result.success(map);
}
private static boolean isUpdateRows(Patient bindInfo, PatientDao patientDao) {
return patientDao.updateMyself(bindInfo);
}
/**
* [无证绑定]参数校验
*/
@ -420,38 +439,57 @@ public class PatientService {
*/
public void wh_gmc_patient_ids() {
List<Patient> patients = new PatientDao().selectNoneGmcList();
if (patients.isEmpty()) {
return;
}
log.warn("[医共体]患者id替换开始......共:[{}]条", patients.size());
PatientDao patientDao = new PatientDao();
int errNum = 0;
int index = 0;
for (Patient patient : patients) {
String gmcPatientId = null; // 医共体患者id
index = index + 1;
log.warn("[医共体替换]index={}", index);
Integer id = patient.getId();
String hisPatientId = patient.getPatientId(); // 旧id
Patient hisPatient;
if (!HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType())) { // 不为无证绑定
try {
hisPatient = new HisPatientDao().bind(false, patient);
if (hisPatient == null || ObjectUtils.isEmpty(hisPatient.getPatientId())) {
log.warn("[医共体]患者id替换-调用HIS绑定接口异常,未返回患者信息 id={}, hisPatientId={}", id, hisPatientId);
if (HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType()) || ObjectUtils.isEmpty(patient.getIdCardNo())) { // 无证绑定
continue;
}
gmcPatientId = hisPatient.getPatientId();
} catch (Exception e) {
log.warn(e.getMessage());
String gmcPatientId = null;
Integer id = patient.getId();
String hisPatientId = patient.getPatientId(); // 旧id
// 有证
boolean hasCard = !HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType()) && !ObjectUtils.isEmpty(patient.getIdCardNo());
if (hasCard) {
gmcPatientId = new HisPatientDao().getGMCPatientId(hisPatientId); // 医共体患者id
if (ObjectUtils.isEmpty(gmcPatientId)) {
log.warn("[医共体id]替换失败 hisPatientId={}", hisPatientId);
continue;
}
}
boolean isUpdate = patientDao.updateGmcInfo(patient.getId(), patient.getIdCardNo(), patient.getCardType(), gmcPatientId, hisPatientId);
// Patient hisPatient;
// if (!HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType())) { // 不为无证绑定
// try {
// hisPatient = new HisPatientDao().getGMCPatientId(false, patient);
// if (hisPatient == null || ObjectUtils.isEmpty(hisPatient.getPatientId())) {
// log.warn("[医共体]患者id替换-调用HIS绑定接口异常,未返回患者信息 id={}, hisPatientId={}", id, hisPatientId);
// continue;
// }
// gmcPatientId = hisPatient.getPatientId();
// } catch (Exception e) {
// log.warn(e.getMessage());
// continue;
// }
// }
boolean isUpdate = patientDao.updateGmcInfo(hasCard ,id, gmcPatientId, hisPatientId);
if (!isUpdate) {
errNum = errNum + 1;
log.warn("[医共体]患者id替换更新数据失败 id={}, hisPatientId={}", id, hisPatientId);
}
log.warn("[医共体]患者id替换 共:[{}]条, 失败:[{}]条", patients.size(), errNum);
}
log.warn("[医共体]患者id替换 共:[{}]条, 失败:[{}]条", patients.size(), errNum);
}
}

@ -22,6 +22,8 @@ public class WeChatConfig {
// 域名
public static final String DOMAIN;
// 备用域名(主要用于医共体认证或作为第二域名)
public static final String BACKUP_DOMAIN;
// 请求路径
public static final String BASE_REQ_URL;
// 静态资源请求路径
@ -71,6 +73,7 @@ public class WeChatConfig {
MCH_KEY = config.getString("wx.mch_key");
DOMAIN = config.getString("wx.domain");
BACKUP_DOMAIN = config.getString("wx.backup_domain");
DEPLOY_SERVER_NAME = config.getString("wx.deploy_server_name");
WEB_STATIC_PATH = config.getString("wx.web_static_path", "");
@ -112,15 +115,26 @@ public class WeChatConfig {
return BASE_REQ_URL;
}
public static String getBaseURL(boolean isHttps) {
if (isHttps) {
return getHttpsBaseURL();
}
return getBaseURL();
}
public static String getHttpsBaseURL() {
return URLHelper.URLToHttps(BASE_REQ_URL);
}
public static String getBaseURL(boolean isHttps) {
public static String getBackupURL(boolean isHttps) {
if (ObjectUtils.isEmpty(BACKUP_DOMAIN)) { // 为空返回主域名
return getBaseURL(isHttps);
}
String url = toReqUrl(BACKUP_DOMAIN + "/" + DEPLOY_SERVER_NAME);
if (isHttps) {
return getHttpsBaseURL();
return URLHelper.URLToHttps(url);
}
return getBaseURL();
return url;
}
/**

@ -79,8 +79,10 @@ public class QServlet extends HttpServlet {
groupTreatNum = hasTreatNum ? ("&treatNum=" + groupTreatNum) : "";
String params = "?p=" + patientId + "&enp=" + AesWxHelper.encode(patientId) + cardNo + groupTreatNum;
if (MerchantEnum.WX.equals(merchantEnum)) {
response.sendRedirect(WeChatConfig.getWebReqURL() + "pay-qr-recipe.html?p=" + patientId + "&enp=" + AesWxHelper.encode(patientId) + cardNo + groupTreatNum);
response.sendRedirect(WeChatConfig.getWebReqURL() + "pay-qr-recipe.html" + params);
}
}

@ -57,7 +57,7 @@ public class AesWxHelper extends AesHelper {
}
public static void main(String[] args) {
System.out.println(encode("899065"));
System.out.println(encode("2088732153433283"));
// System.out.println(decode("E6835E243069406F53EC8464898B37C0"));
}
}

@ -22,7 +22,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -36,7 +35,7 @@ public class WxAuthHelper {
private static final String P_SUFFIX = ":"; // 后缀
private static final String AUTH_SESSION_ID_NAME = "SID"; // session name标识
private static final String GMC_ID = "GMCId"; // 主体服务器-sessionId
private static final String GMC_SID = "GMC_SID"; // 主体服务器-sessionId
private static final String OPENID = "openid";
public static String getSessionOpenid(HttpServletRequest request) {
@ -48,15 +47,18 @@ public class WxAuthHelper {
public static String auth(HttpServletRequest request, HttpServletResponse response, boolean isUserInfo) {
try {
String code = request.getParameter("code");
String state = request.getParameter("state"); // base64
Map<String, String> paramsMap = getParamsMap(request.getParameter("p"));
String param = request.getParameter("p"); // base64
Map<String, String> authStateMap = getMapVal(request.getParameter("state"));
log.info("[认证授权] code={}, state={}, paramsMap={}", code, state, JsonHelper.toJsonString(paramsMap));
log.info("[认证授权] code={}, param={}, authStateMap={}", code, param, JsonHelper.toJsonString(authStateMap));
state = state == null ? "" : URLDecoder.decode(Base64Helper.decode(state), "UTF-8");
String authSessionId = AesWxHelper.decode(paramsMap.get(AUTH_SESSION_ID_NAME));
param = URLHelper.decodeURL(Base64Helper.decode(param));
if (param == null) {
param = "";
}
log.info("[认证授权-解码] authSessionId={}, state={}", authSessionId, state);
String authSessionId = AesWxHelper.decode(authStateMap.get(AUTH_SESSION_ID_NAME));
log.info("[认证授权-解码] authSessionId={}, param={}", authSessionId, param);
SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code);
log.info("[认证授权]信息 snsToken={}", JsonHelper.toJsonString(snsToken));
@ -109,16 +111,16 @@ public class WxAuthHelper {
}
if (WeChatConfig.HAS_HTTPS_BY_BASE_URL) { // 强制为https
String httpsURL = URLHelper.URLToHttps(state);
state = httpsURL == null ? "" : httpsURL;
String httpsURL = URLHelper.URLToHttps(param);
param = httpsURL == null ? "" : httpsURL;
}
if (state.contains(".html")) { // 网页授权配置
return state;
if (param.contains(".html")) { // 网页授权配置
return param;
} else {
String baseUrl = WeChatConfig.getBaseURL();
if (baseUrl != null && state.contains(baseUrl)) {
return state;
if (baseUrl != null && param.contains(baseUrl)) {
return param;
}
}
} catch (Exception e) {
@ -200,7 +202,7 @@ public class WxAuthHelper {
// log.info("cacheTokenOpenId={}, sessionOpenId={}", cacheTokenOpenId, sessionOpenId);
// 判断是否有主体id
Object sessionGmcOpenId = session.getAttribute(GMC_ID);
Object sessionGmcOpenId = session.getAttribute(GMC_SID);
String gmcOpenId = sessionGmcOpenId == null ? null : sessionGmcOpenId.toString();
log.info("[向主服务器请求认证] gmcOpenId={}", gmcOpenId);
@ -219,7 +221,7 @@ public class WxAuthHelper {
new GMCUserService().addInfo(sessionOpenId, gmcOpenId, null, CodeHelper.get32UUID());
if (sessionGmcOpenId == null) {
session.setAttribute(GMC_ID, gmcOpenId);
session.setAttribute(GMC_SID, gmcOpenId);
}
// 查询返回数据
@ -266,7 +268,7 @@ public class WxAuthHelper {
log.info("[req:主服务器认证]wxOpenId={}, gmcOpenId={}", sessionOpenId, openId);
if (!ObjectUtils.isEmpty(gmcOpenId)) { // 授权主体完成认证
session.setAttribute(GMC_ID, gmcOpenId);
session.setAttribute(GMC_SID, gmcOpenId);
new GMCUserService().addInfo(sessionOpenId, gmcOpenId, null, CodeHelper.get32UUID());
AuthResultData authResultData = getCacheUserData(request, sessionOpenId, state, isUserInfo, authSessionId);
@ -396,27 +398,26 @@ public class WxAuthHelper {
String api = isFindUserInfo ? "u_auth" : "b_auth";
String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base";
String enUID = toURLParam(GMC_ID, AesWxHelper.encode(UID, true));
String enUID = toURLParam(GMC_SID, AesWxHelper.encode(UID, true));
String enSID = toURLParam(AUTH_SESSION_ID_NAME, AesWxHelper.encode(SID, true));
String params = enSID + enUID;
try {
params = ObjectUtils.isEmpty(params) ? "" : URLEncoder.encode(params, "UTF-8");
log.warn("[认证链接参数]params={}", params);
} catch (Exception e) {
log.error(e.getMessage());
}
String authState = URLHelper.encodeURL((enSID + enUID), false);
String serverName = request.getServerName();
log.info("[微信认证]域名 serverName={}", serverName);
state = OAUTH_URL + WeChatConfig.getBaseURL(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)) +
String baseURL = (!ObjectUtils.isEmpty(WeChatConfig.BACKUP_DOMAIN) && WeChatConfig.BACKUP_DOMAIN.contains(serverName))
? WeChatConfig.getBackupURL(isHttpsWithProxy(request))
: WeChatConfig.getBaseURL(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request));
log.warn("[微信认证][getAuthUrl] baseURL={}, serverName={}, state={}, authState={}", baseURL, serverName, state, authState);
state = OAUTH_URL + baseURL +
"wx_auth/" + api +
"?p=" + params +
"?p=" + state + // 发起认证的网页链接
"&response_type=code" +
"&scope=" + scope +
"&forcePopup=true" +
"&state=" + state + // state位置固定
"&state=" + authState + // state位置固定
"#wechat_redirect";
log.warn("[认证授权链接]state={}", state);
log.warn("[认证授权链接]{}", state);
return Base64Helper.encode(state);
}
@ -437,7 +438,7 @@ public class WxAuthHelper {
return P_PREFIX + key + P_SUFFIX + val;
}
public static Map<String, String> getParamsMap(String params) {
public static Map<String, String> getMapVal(String params) {
Map<String, String> paramsMap = new HashMap<>();
try {
if (ObjectUtils.isEmpty(params)) {

@ -345,10 +345,19 @@ public class WxPayHelper {
// micropay.setDetail("描述"); // 商品描述
Order wxOrder;
log.info("【微信】[扫码盒子]下单开始...[{}]", outTradeNo);
long begTime = System.currentTimeMillis(); // 结束时间
MicropayResult micropayResult = PayMchAPI.payMicropay(micropay, mchKey);
long endTime = System.currentTimeMillis(); // 结束时间
long takeTime = endTime - begTime;
if (takeTime > 6000) {
log.warn("【微信】[扫码盒子]下单耗时超过6s [{}]", outTradeNo);
}
log.info("【微信】[扫码盒子]下单完成-耗时:[{}] [{}]", (takeTime + "ms"), outTradeNo);
Order wxOrder;
if (micropayResult == null) {
log.warn("【微信】[盒子支付]下单异常 outTradeNo={}", outTradeNo);
log.error("【微信】[盒子支付]下单异常 outTradeNo={}", outTradeNo);
wxOrder = waitMicoPay(outTradeNo); // 可能会出现支付成功,但是接口响应失败的情况
if (wxOrder != null) {
return wxOrder;
@ -368,7 +377,6 @@ public class WxPayHelper {
order.setOpenid(openid);
order.setBankTransNo(bankTransNo);
if (FAIL.equals(micropayResult.getReturn_code())) { // 调用接口异常
log.info("【微信】[盒子支付]调用接口异常 outTradeNo={}, bankTransNo={}, returnCode={}, returnMsg={}", outTradeNo, bankTransNo, micropayResult.getReturn_code(), micropayResult.getReturn_msg());
order.setErrorCode(micropayResult.getReturn_code());
@ -391,8 +399,9 @@ public class WxPayHelper {
}
}
// 免密支付
Thread.sleep(2000); // 2s
Thread.sleep(100);
wxOrder = queryOrder(outTradeNo);
// 长时间未支付
if (USER_PAYING.equals(wxOrder.getTradeState()) || PAY_ERROR.equals(wxOrder.getTradeState())) {
@ -404,6 +413,8 @@ public class WxPayHelper {
wxOrder.setErrorMsg("订单已撤销");
}
}
log.info("【微信】[扫码盒子]免密支付-耗时:[{}] [{}]", ((System.currentTimeMillis() - begTime) + "ms"), outTradeNo);
return wxOrder;
} catch (Exception e) {
log.info("【微信】[盒子支付]异常 {}", e.getMessage());
@ -439,9 +450,9 @@ public class WxPayHelper {
// 支付失败
if (PAY_ERROR.equals(wxOrder.getTradeState())) {
if (i == 1) {
Thread.sleep(9000); // 等够12s
Thread.sleep(7000); // 等够10s
} else if (i == 2) {
Thread.sleep(6000); // 等够12.5s
Thread.sleep(5500); // 等够10s
}
endTime = System.currentTimeMillis(); // 结束时间

@ -1 +1 @@
# \u5F00\u542F\u5904\u65B9\u9884\u7ED3\u7B97\uFF08\u7B2C2\u5F00\u5173\uFF09\uFF08\u6CE8\u610F\u8BE5\u914D\u7F6E\u9700\u8054\u7CFBhis\u5F00\u53D1\u8005\u786E\u8BA4\u652F\u6301\u624D\u80FD\u5F00\u542F\uFF0C\u5426\u5219\u5B58\u5728\u98CE\u9669\uFF01\uFF09 his.is_recipe_prepay=false # \u672C\u5730 #his.url=127.0.0.1:8888 # HIS\u662F\u5426\u5F00\u542F\u652F\u4ED8\u5B9D\u5206\u5F00\u5BF9\u8D26 his.is_ali_mer=false # \u662F\u5426\u5F3A\u5236\u6253\u5370webservice\u7684xml\u8FD4\u56DE\u6570\u636E his.is_log_resp=true # \u662F\u5426\u4F20\u9012openid\u7ED9his\u63A8\u9001\u6D88\u606F his.is_push_msg=false #------------------------------- # \u6D4B\u8BD5\u73AF\u5883 his.dev_url=200.200.200.105:8888 # \u533B\u4FDD=========================== # \u65E7\u914D\u7F6E his.md_url=127.0.0.1:7777 # \u5FAE\u4FE1\u533B\u4FDD his.wx_med_url=10.20.10.7:7885 # \u652F\u4ED8\u5B9D\u533B\u4FDD his.ali_med_url=10.20.10.7:7885 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u77F3\u6797\u6D4B\u8BD5 his.url=200.200.200.105:8888 # \u6D4B\u8BD5============================================================ # \u5FB7\u5B8F\u4E2D\u533B #his.url=200.200.200.60:8888 # \u7EA2\u6CB3\u5DDE\u533B\u9662 #his.url=10.20.10.6:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # \u5B81\u8497\u5987\u5E7C #his.url=172.19.3.15:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.39:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u7EA2\u6CB3 #his.url=10.20.10.6:8888 # \u7EA2\u6CB3\u533B\u4FDD #his.url=10.20.10.6:8888 #his.url=192.168.12.10:8888 #his.md_url=192.168.1.128:7885 #his.dev_url=10.20.10.6:9988 # \u6C38\u80DC #his.url=200.200.200.20:8888 # \u5FB7\u5B8F\u4E2D\u533B #his.url=200.200.200.60:8888 # \u534E\u576A #his.url=192.168.1.115:8888 # \u8499\u81EA\u4E2D\u533B #his.url=192.168.0.228:8888 # \u7389\u9F99 #his.url=192.168.0.17:8888 # \u4E91\u9F99 #his.url=200.200.200.69:8888 # #his.url=172.16.10.15:8888 # \u7984\u529D\u949F\u7231 #his.url=200.200.200.5:8888 # \u8499\u81EA\u5E02\u4EBA\u6C11\u533B\u9662 #his.url=200.200.200.174:8080 # \u5143\u8C0B #his.url=200.200.200.29:8888 # \u5143\u8C0B\u533B\u4FDD #his.dev_url=200.200.200.36:9999 # \u8292\u5E02 #his.url=192.168.100.8:8888 # \u7EA2\u6CB3\u5987\u5E7C\u4FDD\u5065\u9662 #his.url=192.168.1.204:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # #his.url=10.10.11.23:8888 # \u77F3\u6797 #his.url=192.168.10.10:8888 # \u5BCC\u6C11 #his.url=200.200.201.27:8888 # \u897F\u53CC\u7248\u7EB3 #his.url=10.10.11.23:8888 #wx.password=ynxbd@6910
# \u5F00\u542F\u5904\u65B9\u9884\u7ED3\u7B97\uFF08\u7B2C2\u5F00\u5173\uFF09\uFF08\u6CE8\u610F\u8BE5\u914D\u7F6E\u9700\u8054\u7CFBhis\u5F00\u53D1\u8005\u786E\u8BA4\u652F\u6301\u624D\u80FD\u5F00\u542F\uFF0C\u5426\u5219\u5B58\u5728\u98CE\u9669\uFF01\uFF09 his.is_recipe_prepay=false # \u672C\u5730 #his.url=127.0.0.1:8888 # HIS\u662F\u5426\u5F00\u542F\u652F\u4ED8\u5B9D\u5206\u5F00\u5BF9\u8D26 his.is_ali_mer=false # \u662F\u5426\u5F3A\u5236\u6253\u5370webservice\u7684xml\u8FD4\u56DE\u6570\u636E his.is_log_resp=true # \u662F\u5426\u4F20\u9012openid\u7ED9his\u63A8\u9001\u6D88\u606F his.is_push_msg=false #------------------------------- # \u6D4B\u8BD5\u73AF\u5883 his.dev_url=200.200.200.105:8888 # \u533B\u4FDD=========================== # \u65E7\u914D\u7F6E his.md_url=127.0.0.1:7777 # \u5FAE\u4FE1\u533B\u4FDD his.wx_med_url=10.20.10.7:7885 # \u652F\u4ED8\u5B9D\u533B\u4FDD his.ali_med_url=10.20.10.7:7885 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u77F3\u6797\u6D4B\u8BD5 #his.url=200.200.200.105:8888 # \u6D4B\u8BD5============================================================ # \u5FB7\u5B8F\u4E2D\u533B #his.url=200.200.200.60:8888 # \u7EA2\u6CB3\u5DDE\u533B\u9662 #his.url=10.20.10.6:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # \u5B81\u8497\u5987\u5E7C #his.url=172.19.3.15:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.39:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u7EA2\u6CB3 #his.url=10.20.10.6:8888 # \u7EA2\u6CB3\u533B\u4FDD #his.url=10.20.10.6:8888 #his.url=192.168.12.10:8888 #his.md_url=192.168.1.128:7885 #his.dev_url=10.20.10.6:9988 # \u6C38\u80DC #his.url=200.200.200.20:8888 # \u5FB7\u5B8F\u4E2D\u533B #his.url=200.200.200.60:8888 # \u534E\u576A #his.url=192.168.1.115:8888 # \u8499\u81EA\u4E2D\u533B #his.url=192.168.0.228:8888 # \u7389\u9F99 his.url=192.168.0.17:8888 # #his.url=172.16.10.15:8888 # \u7984\u529D\u949F\u7231 #his.url=200.200.200.5:8888 # \u8499\u81EA\u5E02\u4EBA\u6C11\u533B\u9662 #his.url=200.200.200.174:8080 # \u5143\u8C0B #his.url=200.200.200.29:8888 # \u5143\u8C0B\u533B\u4FDD #his.dev_url=200.200.200.36:9999 # \u8292\u5E02 #his.url=192.168.100.8:8888 # \u7EA2\u6CB3\u5987\u5E7C\u4FDD\u5065\u9662 #his.url=192.168.1.204:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # #his.url=10.10.11.23:8888 # \u77F3\u6797 #his.url=192.168.10.10:8888 # \u5BCC\u6C11 #his.url=200.200.201.27:8888 # \u897F\u53CC\u7248\u7EB3 #his.url=10.10.11.23:8888 #wx.password=ynxbd@6910
Loading…
Cancel
Save