diff --git a/src/main/java/com/ynxbd/common/TestA.java b/src/main/java/com/ynxbd/common/TestA.java index 7c9f73a..498e963 100644 --- a/src/main/java/com/ynxbd/common/TestA.java +++ b/src/main/java/com/ynxbd/common/TestA.java @@ -1,5 +1,9 @@ package com.ynxbd.common; +import cn.hutool.core.util.IdcardUtil; +import com.ynxbd.common.helper.common.AesMicroHelper; +import com.ynxbd.common.helper.common.JsonHelper; +import com.ynxbd.common.helper.http.OkHttpHelper; import com.ynxbd.wx.wxfactory.AesWxHelper; import lombok.extern.slf4j.Slf4j; @@ -126,9 +130,9 @@ public class TestA { // System.out.println(removeIds); // } - public static void main(String[] args) { - System.out.println(AesWxHelper.encode("1")); - System.out.println(AesWxHelper.encode("100004220302")); - System.out.println(AesWxHelper.encode("100004219291")); - } +// +// public static void main(String[] args) { +// System.out.println(AesWxHelper.decode("562CF576AEC37AA2EC0CCB873ABF67A3060B9C01AD9B8068C43FEAEDDB00E5A6")); +// } + } \ No newline at end of file diff --git a/src/main/java/com/ynxbd/common/action/PatientAction.java b/src/main/java/com/ynxbd/common/action/PatientAction.java index 056149b..f9245f3 100644 --- a/src/main/java/com/ynxbd/common/action/PatientAction.java +++ b/src/main/java/com/ynxbd/common/action/PatientAction.java @@ -63,7 +63,7 @@ public class PatientAction extends BaseAction { return Result.error(ResultEnum.PARAM_IS_DEFECT); } - Patient patient = new PatientService().queryPatientByCardNo(cardNo); + Patient patient = new PatientService().queryHisPatientByCardNo(cardNo); if (patient == null) { return Result.error(ResultEnum.PATIENT_NOT_FOUND); } diff --git a/src/main/java/com/ynxbd/common/action/RecipeAction.java b/src/main/java/com/ynxbd/common/action/RecipeAction.java index b48edc7..784a03b 100644 --- a/src/main/java/com/ynxbd/common/action/RecipeAction.java +++ b/src/main/java/com/ynxbd/common/action/RecipeAction.java @@ -144,11 +144,11 @@ public class RecipeAction extends BaseAction { return Result.error(ResultEnum.PARAM_IS_DEFECT); } int days = DateHelper.intervalDays(begDate, endDate, true); - List hisRecipes = new HisRecipeDao().getRxUnPay(null, patientId, "", days); + List hisRxList = new HisRecipeDao().getRxUnPay(null, patientId, "", days); List resultList = new ArrayList<>(); - for (HisRecipe hisRecipe : hisRecipes) { - if (hisRecipe.getDate() != null && DateHelper.inDateRange(begDate, endDate, hisRecipe.getDate(), DateHelper.DateEnum.yyyy_MM_dd)) { - resultList.add(hisRecipe); + for (HisRecipe rxItem : hisRxList) { + if (rxItem.getDate() != null && DateHelper.inDateRange(begDate, endDate, rxItem.getDate(), DateHelper.DateEnum.yyyy_MM_dd)) { + resultList.add(rxItem); } } return Result.success(resultList); diff --git a/src/main/java/com/ynxbd/common/action/pay/JYPSEnum.java b/src/main/java/com/ynxbd/common/action/pay/JYPSEnum.java new file mode 100644 index 0000000..da3911a --- /dev/null +++ b/src/main/java/com/ynxbd/common/action/pay/JYPSEnum.java @@ -0,0 +1,49 @@ +package com.ynxbd.common.action.pay; + +import com.ynxbd.jy.bean.enums.JYBusinessTypeEnum; +import com.ynxbd.jy.bean.enums.JYOrderTypeEnum; +import lombok.ToString; + +@ToString +public enum JYPSEnum { + NO(PEnum.NO, JYOrderTypeEnum._002, JYBusinessTypeEnum.B999), + + REG(PEnum.REG, JYOrderTypeEnum._001, JYBusinessTypeEnum.B101), + + RECIPE(PEnum.RECIPE, JYOrderTypeEnum._002, JYBusinessTypeEnum.B201), + + IN_HOSP(PEnum.IN_HOSP, JYOrderTypeEnum._003, JYBusinessTypeEnum.B301), + + OUT_HOSP(PEnum.OUT_HOSP, JYOrderTypeEnum._903, JYBusinessTypeEnum.B302), + + OL_REG(PEnum.OL_REG, JYOrderTypeEnum._001, JYBusinessTypeEnum.B101), + + MED_RECORD(PEnum.MED_RECORD, JYOrderTypeEnum._001, JYBusinessTypeEnum.B101), + + OUT_COLLECT(PEnum.OUT_COLLECT, JYOrderTypeEnum._012, JYBusinessTypeEnum.B999), + + TPP_QR_REG(PEnum.TPP_QR_REG, JYOrderTypeEnum._001, JYBusinessTypeEnum.B101), + + PEIS_RESERVE(PEnum.PEIS_RESERVE, JYOrderTypeEnum._904, JYBusinessTypeEnum.B999), + ; + + public final PEnum PS; + public final JYOrderTypeEnum ORDER_TYPE; + public final JYBusinessTypeEnum BUSINESS_TYPE; + + JYPSEnum(PEnum PS, JYOrderTypeEnum ORDER_TYPE, JYBusinessTypeEnum BUSINESS_TYPE) { + this.PS = PS; + this.ORDER_TYPE = ORDER_TYPE; + this.BUSINESS_TYPE = BUSINESS_TYPE; + } + + public static JYPSEnum findEnum(PEnum ps) { + for (JYPSEnum item : JYPSEnum.values()) { + if (item.PS.equals(ps)) { + return item; + } + } + return NO; + } + +} diff --git a/src/main/java/com/ynxbd/common/action/pay/JYPayAction.java b/src/main/java/com/ynxbd/common/action/pay/JYPayAction.java index 708f533..f7c0298 100644 --- a/src/main/java/com/ynxbd/common/action/pay/JYPayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/JYPayAction.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.ynxbd.common.action.base.BaseAction; import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.bean.pay.ApiPayNotify; +import com.ynxbd.common.bean.pay.Order; import com.ynxbd.common.bean.pay.ReqOrder; import com.ynxbd.common.helper.common.HttpHelper; import com.ynxbd.common.helper.common.JsonHelper; @@ -49,20 +50,20 @@ public class JYPayAction extends BaseAction { String title = "支付测试"; ReqOrder req = new ReqOrder(); - req.setPatientName("小王"); - req.setPatientGender("男"); - req.setPatientAge("18"); - req.setPatientTel("15559603353"); - req.setTreatNum("T001"); - req.setPatientIdCardNo("532331199910053810"); - req.setPatientId("1000001"); - - JYOrder jyOrder = new JYOrder(); - jyOrder.orderTypeEnum = JYOrderTypeEnum._001; // 挂号费 - jyOrder.businessTypeEnum = JYBusinessTypeEnum.B102; - - req.setJyOrder(jyOrder); - JSONObject prepay = JYPayHelper.createOrder(MerchantEnum.JY, title, merOrderNum, totalFee.toString(), PEnum.REG.CODE, ip, payOpenId, openid, req); +// req.setPatientName("小王"); +// req.setPatientGender("男"); +// req.setPatientAge("18"); +// req.setPatientTel("15559603353"); +// req.setTreatNum("T001"); +// req.setPatientIdCardNo("532331199910053810"); +// req.setPatientId("1000001"); + +// JYOrder jyOrder = new JYOrder(); +// jyOrder.orderTypeEnum = JYOrderTypeEnum._001; // 挂号费 +// jyOrder.businessTypeEnum = JYBusinessTypeEnum.B102; +// +// req.setJyOrder(jyOrder); + JSONObject prepay = JYPayHelper.createOrder(MerchantEnum.JY, title, merOrderNum, totalFee.toString(), PEnum.REG, ip, payOpenId, openid, req); if (prepay == null) { return Result.error(ResultEnum.PAY_ERROR_ORDER); // 下单异常 } @@ -79,19 +80,16 @@ public class JYPayAction extends BaseAction { // outRefundNo, refundFee, outTradeNo, bankMerchantNo, tradeNo); // // ReqOrder req = new ReqOrder(); -// req.setPatientName("小王"); -// req.setPatientGender("男"); -// req.setPatientAge("18"); -// req.setPatientTel("15559603353"); -// req.setTreatNum("T001"); -// req.setPatientIdCardNo("532331199910053810"); -// req.setPatientId("1000001"); +//// req.setPatientName("小王"); +//// req.setPatientGender("男"); +//// req.setPatientAge("18"); +//// req.setPatientTel("15559603353"); +//// req.setTreatNum("T001"); +//// req.setPatientIdCardNo("532331199910053810"); +//// req.setPatientId("1000001"); // -// JSONObject prepay = JYPayHelper.refundPayOrder(JYBusinessTypeEnum.B102, req, outRefundNo, refundFee, outTradeNo, bankMerchantNo, tradeNo); -// if (prepay == null) { -// return Result.error(); // 下单异常 -// } -// return Result.success(prepay); +// Order order = JYPayHelper.refundPayOrder(JYBusinessTypeEnum.B102, req, outRefundNo, refundFee, outTradeNo, bankMerchantNo, tradeNo); +// return Result.success(order); // } @@ -123,10 +121,12 @@ public class JYPayAction extends BaseAction { } Map params = reqParamsToMap(); + log.info("[京颐]回调信息: [{}]", params); + String sign = JYPayRSAUtil.createSign(params, JYPayConfig.PRIVATE_KEY); log.info("[sign]{}", sign); - ApiPayNotify info = JYPayHelper.jyPayNotify(reqParamsToBean(JYPayNotify.class), notifyType); + ApiPayNotify info = JYPayHelper.jyPayNotify(params, notifyType); log.info("【京颐】[{}]收到[{}]通知-{}", pEnum.NAME, (info.isRefundOrder() ? "退款" : "支付"), JsonHelper.toJsonString(info)); Result.respXml(WxRespHelper.respOk()); // 收到请求-解析成功 diff --git a/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java b/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java index 94c6168..062a601 100644 --- a/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java @@ -273,9 +273,9 @@ public class MedicalAction extends BaseAction { return Result.error(ResultEnum.PARAM_IS_BLANK); } String payWay = getReqParamByKey("payWay"); - + Integer rxType = getReqParamByKey("rxType", Integer.class); Recipe rxOrder = JsonHelper.copy(order, Recipe.class); - return new MedicalService().createRxOrder(merchantEnum, rxOrder, serverEnum, recipeJson, payWay); + return new MedicalService().createRxOrder(merchantEnum, rxOrder, serverEnum, recipeJson, payWay, rxType); case OUT_HOSP: PayInHosp outHospOrder = JsonHelper.copy(order, PayInHosp.class); diff --git a/src/main/java/com/ynxbd/common/action/pay/PayAction.java b/src/main/java/com/ynxbd/common/action/pay/PayAction.java index 306c295..fa2a3f5 100644 --- a/src/main/java/com/ynxbd/common/action/pay/PayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/PayAction.java @@ -92,7 +92,7 @@ public class PayAction extends BaseAction { * @param awaitSecond 待秒数,0继续执行不等待(不传或null 为0) */ @Action("recipePay") - public Result recipePay(boolean isPrepay, String payCode, String payOpenId, String openid, String patientId, String treatNum, String totalFee, String recipeJson, String payWay, Integer awaitSecond) { + public Result recipePay(boolean isPrepay, String payCode, String payOpenId, String openid, String patientId, String treatNum, String totalFee, String recipeJson, String payWay, Integer rxType, Integer awaitSecond) { try { MerchantEnum merchantEnum = MerchantEnum.findEnumByCode(payCode); if (merchantEnum == null) { // 支付方式异常 @@ -109,7 +109,7 @@ public class PayAction extends BaseAction { } } - Result result = rxService.medInsPrepay(merchantEnum, payOpenId, openid, patientId, treatNum, totalFee, recipeJson, payWay, awaitSecond, isHttpsWithProxy()); + Result result = rxService.medInsPrepay(merchantEnum, payOpenId, openid, patientId, treatNum, totalFee, recipeJson, payWay, rxType, awaitSecond, isHttpsWithProxy()); if (!result.isOK() || result.getData() != null) { // 业务错误 || 存在返回数据-需提前返回 return result; } @@ -136,7 +136,7 @@ public class PayAction extends BaseAction { } // 订单信息预存 - if (!rxService.saveRxData(merchantEnum, payOpenId, openid, recipeJson, payWay, patientId, treatNum, totalFee, new ApiPrepayResp(respJson))) { + if (!rxService.saveRxData(merchantEnum, payOpenId, openid, recipeJson, payWay, rxType, patientId, treatNum, totalFee, new ApiPrepayResp(respJson))) { log.info("{} [处方支付]预存支付信息失败 patientId={}", merchantEnum.NAME, patientId); return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); } diff --git a/src/main/java/com/ynxbd/common/bean/pay/ApiPayNotify.java b/src/main/java/com/ynxbd/common/bean/pay/ApiPayNotify.java index dc51e7e..f2e4966 100644 --- a/src/main/java/com/ynxbd/common/bean/pay/ApiPayNotify.java +++ b/src/main/java/com/ynxbd/common/bean/pay/ApiPayNotify.java @@ -21,6 +21,7 @@ public class ApiPayNotify { private String mixTradeNo; private String transactionId; private String refundTransId; + private String refundTime; private BigDecimal totalFee; diff --git a/src/main/java/com/ynxbd/common/bean/pay/Recipe.java b/src/main/java/com/ynxbd/common/bean/pay/Recipe.java index 26be9cd..8ba90d2 100644 --- a/src/main/java/com/ynxbd/common/bean/pay/Recipe.java +++ b/src/main/java/com/ynxbd/common/bean/pay/Recipe.java @@ -46,6 +46,6 @@ public class Recipe extends Order implements Serializable { private String feeId; // 预结算信息 private String feeInfo; - - + // 处方类型[1:普通处方; 10:互联网医院处方; 11:互联网医院流转处方; 15:生育门诊; 20:慢特病处方;] + private Integer rxType; } diff --git a/src/main/java/com/ynxbd/common/bean/pay/ReqOrder.java b/src/main/java/com/ynxbd/common/bean/pay/ReqOrder.java index b498e77..47176cd 100644 --- a/src/main/java/com/ynxbd/common/bean/pay/ReqOrder.java +++ b/src/main/java/com/ynxbd/common/bean/pay/ReqOrder.java @@ -2,8 +2,6 @@ package com.ynxbd.common.bean.pay; import com.ynxbd.jy.bean.JYOrder; -import com.ynxbd.jy.bean.enums.JYBusinessTypeEnum; -import com.ynxbd.jy.bean.enums.JYOrderTypeEnum; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -12,7 +10,7 @@ import lombok.ToString; import java.io.Serializable; import java.math.BigDecimal; -// 医保请求参数 +// 京颐请求参数 @Setter @Getter diff --git a/src/main/java/com/ynxbd/common/bean/xk/XKChargeOrRefund.java b/src/main/java/com/ynxbd/common/bean/xk/XKChargeOrRefund.java new file mode 100644 index 0000000..b2df083 --- /dev/null +++ b/src/main/java/com/ynxbd/common/bean/xk/XKChargeOrRefund.java @@ -0,0 +1,106 @@ +package com.ynxbd.common.bean.xk; +/* + * Copyright (c) 2022 + * User:Administrator + * File:XKMedicineDeliver.java + * Date:2022/12/01 13:58:01 + */ + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.math.BigDecimal; +import java.util.List; + +// 4.3.1.11 收费/退费 ChargeOrRefund +@Getter +@Setter +@ToString +@NoArgsConstructor +public class XKChargeOrRefund { + private String callNo; + /** + * 患者就诊卡证类型 + */ + private String idcardTypeCode; + /** + * 患者就诊卡证号码 + */ + private String idcardNo; + /** + * 姓名 + */ + private String name; + /** + * 性别代码 + */ + private String genderCode; + /** + * 出生日期 + */ + private String birthDate; + /** + * 门诊编号 + */ + private String visitNo; + /** + * 结算序号 + */ + private String accountNo; + /** + * 原结算序号 + */ + private String originalAccountNo; + /** + * 支付平台订单号 + */ + private String orderNo; + /** + * 总费用(元) + */ + private BigDecimal totalFee; + /** + * 自付金额 (元) + */ + private BigDecimal individualPay; + /** + * 收费/退费标志 + */ + private String chargeRefundCode; + /** + * 医疗费用支付途径 + */ + private String payTypeCode; + + /** + * 科室编码 + */ + private String deptCode; + /** + * 科室名称 + */ + private String deptName; + /** + * 科室对应诊疗科目编码 + */ + private String deptClassCode; + /** + * 科室对应诊疗科目名称 + */ + private String deptClassName; + /** + * 收费/退费日期时间 + */ + private String rcdDatetime; + /** + * 收费明细 + */ + private List items; + + public boolean hasRefund() { + return "2".equals(this.chargeRefundCode); + } + +} diff --git a/src/main/java/com/ynxbd/common/bean/xk/XKCostDetail.java b/src/main/java/com/ynxbd/common/bean/xk/XKCostDetail.java new file mode 100644 index 0000000..4e1f210 --- /dev/null +++ b/src/main/java/com/ynxbd/common/bean/xk/XKCostDetail.java @@ -0,0 +1,63 @@ +package com.ynxbd.common.bean.xk; +/* + * Copyright (c) 2022 + * User:Administrator + * File:XKMedicineDeliver.java + * Date:2022/12/01 13:58:01 + */ + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.math.BigDecimal; + +// 4.3.1.11.1 收费明细 CostDetail +@Getter +@Setter +@ToString +@NoArgsConstructor +public class XKCostDetail { + /** + * 项目明细编号 + */ + private String projDeno; + /** + * 项目名称 (包含药品) + */ + private String projName; + /** + * 收费/退费标志 + */ + private String chargeRefundCode; + /** + * 收费项目监管分类代码 + */ + private String statCatCode; + /** + * 收费项目财务分类代码 + */ + private String pinCatCode; + /** + * 是否属于门诊医保项目 + */ + private String ifOutMedIns; + /** + * 项目数量 + */ + private BigDecimal projCnt; + /** + * 项目单价 (元) + */ + private BigDecimal projUnitPrice; + + /** + * 项目总价 (元) + */ + private BigDecimal projAmount; + /** + * 项目自付金额 (元) + */ + private BigDecimal individualPay; +} diff --git a/src/main/java/com/ynxbd/common/dao/RxDao.java b/src/main/java/com/ynxbd/common/dao/RxDao.java index d0c8c02..abb9e29 100644 --- a/src/main/java/com/ynxbd/common/dao/RxDao.java +++ b/src/main/java/com/ynxbd/common/dao/RxDao.java @@ -73,7 +73,7 @@ public class RxDao { * @return 是否存储成功 */ public boolean insertMedical(Recipe recipe) { - String sql = "insert into pay(updateTime, hisStatus, payStatus, openId, patientId, payWay, payMoney, totalFee, outTradeNo, bankTransNo, tradeNo, recipeId, treatNum, authCode, invoiceTransNo, hisTransNo, operateUser, deptCode, deptName, reqDeptCode, reqDeptName, hospitalArea, PayOrdId, AcctFee, HifpFee, ChrgBchno, MdTrtId, MdUserId, RecipeJson, PayMchCode, PayOpenId, BizTradeNo, MixTradeNo) values (now(),?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?,?,?)"; + String sql = "insert into pay(updateTime, hisStatus, payStatus, openId, patientId, payWay, payMoney, totalFee, outTradeNo, bankTransNo, tradeNo, recipeId, treatNum, authCode, invoiceTransNo, hisTransNo, operateUser, deptCode, deptName, reqDeptCode, reqDeptName, hospitalArea, PayOrdId, AcctFee, HifpFee, ChrgBchno, MdTrtId, MdUserId, RecipeJson, RxType, PayMchCode, PayOpenId, BizTradeNo, MixTradeNo) values (now(),?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?,?,?,?)"; return DataBase.insert(sql, ps -> { ps.setInt(1, recipe.getHisStatus()); ps.setInt(2, recipe.getPayStatus()); @@ -107,10 +107,11 @@ public class RxDao { ps.setString(26, recipe.getMdTrtId()); ps.setString(27, recipe.getMdUserId()); ps.setString(28, recipe.getRecipeJson()); - ps.setString(29, recipe.getPayMchCode()); - ps.setString(30, recipe.getPayOpenId()); - ps.setString(31, recipe.getBizTradeNo()); - ps.setString(32, recipe.getMixTradeNo()); + ps.setInt(29, recipe.getRxType()); + ps.setString(30, recipe.getPayMchCode()); + ps.setString(31, recipe.getPayOpenId()); + ps.setString(32, recipe.getBizTradeNo()); + ps.setString(33, recipe.getMixTradeNo()); }) > 0; } @@ -142,10 +143,11 @@ public class RxDao { ps.setString(22, item.getFeeId()); ps.setString(23, item.getFeeInfo()); ps.setString(24, item.getOrderType()); - ps.setString(25, item.getPayMchCode()); - ps.setString(26, item.getPayOpenId()); - ps.setString(27, item.getBizTradeNo()); - ps.setString(28, item.getMixTradeNo()); + ps.setInt(25, item.getRxType()); + ps.setString(26, item.getPayMchCode()); + ps.setString(27, item.getPayOpenId()); + ps.setString(28, item.getBizTradeNo()); + ps.setString(29, item.getMixTradeNo()); } /** @@ -155,7 +157,7 @@ public class RxDao { * @return 是否存储成功 */ public int insertBatch(List rxList) { - String sql = "insert into pay(updateTime, hisStatus, payStatus, openId, patientId, payWay, payMoney, totalFee, outTradeNo, bankTransNo, tradeNo, recipeId, treatNum, authCode, invoiceTransNo, hisTransNo, operateUser, deptCode, deptName, reqDeptCode, reqDeptName, hospitalArea, feeId, feeInfo, orderType, payMchCode, payOpenId, bizTradeNo, mixTradeNo) values (now(),?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?)"; + String sql = "insert into pay(updateTime, hisStatus, payStatus, openId, patientId, payWay, payMoney, totalFee, outTradeNo, bankTransNo, tradeNo, recipeId, treatNum, authCode, invoiceTransNo, hisTransNo, operateUser, deptCode, deptName, reqDeptCode, reqDeptName, hospitalArea, feeId, feeInfo, orderType, rxType, payMchCode, payOpenId, bizTradeNo, mixTradeNo) values (now(),?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?)"; if (rxList.size() == 1) { return DataBase.insert(sql, ps -> { setRxInsertPs(ps, rxList.get(0)); diff --git a/src/main/java/com/ynxbd/common/dao/his/HisPatientDao.java b/src/main/java/com/ynxbd/common/dao/his/HisPatientDao.java index a301a00..b2b36cd 100644 --- a/src/main/java/com/ynxbd/common/dao/his/HisPatientDao.java +++ b/src/main/java/com/ynxbd/common/dao/his/HisPatientDao.java @@ -123,7 +123,7 @@ public class HisPatientDao { * @param patientId 患者id * @return hisResult */ - public JsonResult queryPatientByPatientId(String patientId) throws ServiceException { + public Patient queryHisPatientByPatientId(String patientId) throws ServiceException { if (StringUtils.isEmpty(patientId)) { throw new ServiceException(ResultEnum.PARAM_IS_DEFECT); } @@ -135,8 +135,8 @@ public class HisPatientDao { * * @param cardNo 证件号 */ - public JsonResult queryPatientByCardNo(String cardNo) throws ServiceException { - if (StringUtils.isEmpty(cardNo)) { + public Patient queryHisPatientByCardNo(String cardNo) throws ServiceException { + if (ObjectUtils.isEmpty(cardNo)) { throw new ServiceException(ResultEnum.PARAM_IS_DEFECT); } return queryPatientInfo(cardNo, "0"); @@ -148,7 +148,7 @@ public class HisPatientDao { * @param cardNo 卡号 * @param cardType 类型 {0:身份证; 1:健康卡;999:患者ID(PatientId) 此步骤对于已经获得PatientId 需要查询患者信息的情景。} */ - public JsonResult queryPatientInfo(String cardNo, String cardType) throws ServiceException { + public Patient queryPatientInfo(String cardNo, String cardType) throws ServiceException { if (StringUtils.isEmpty(cardNo) || cardType == null) { throw new ServiceException(ResultEnum.PARAM_IS_DEFECT); } @@ -159,7 +159,15 @@ public class HisPatientDao { Map params = new HashMap<>(); params.put("CardNo", cardNo); params.put("CardType", cardType); - return HisFactory.His().getJsonResult(HisEnum.AP_Query_Patient, params); + JsonResult jsonResult = HisFactory.His().getJsonResult(HisEnum.AP_Query_Patient, params); + if (!jsonResult.success()) { + throw new ServiceException(jsonResult.getMessage()); + } + Patient patient = jsonResult.dataMapToBean(Patient.class); + if (patient == null) { + throw new ServiceException(ResultEnum.DATA_NOT_FOUND); + } + return patient; } diff --git a/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java b/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java index 00db11c..92e61cc 100644 --- a/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java +++ b/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java @@ -152,6 +152,51 @@ public class OkHttpHelper { }); } + public static void postAsync(String url, MapParams mapParams) { + OkHttpClient client = getOkHttpClient(url); + if (client == null) { + return; + } + Map requestParams = new HashMap<>(); + if (mapParams != null) { + mapParams.setParams(requestParams); + } + + // 构建表单参数 + FormBody.Builder formBuilder = new FormBody.Builder(); + for (Map.Entry entry : requestParams.entrySet()) { + formBuilder.add(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString()); + } + RequestBody requestBody = formBuilder.build(); + + Request request = new Request.Builder() + .url(url) + .post(requestBody) + .build(); + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + log.error(e.getMessage(), e); + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + try (ResponseBody responseBody = response.body()) { + if (!response.isSuccessful()) { + if (responseBody != null) { + log.error("请求失败,响应内容:{}", responseBody.string()); + } + } else { + if (responseBody != null) { + log.info("请求成功,响应内容:{}", responseBody.string()); + } + } + } + } + }); + } + // public static String postCookie(String url, RequestBody requestBody, Header header) { // OkHttpClient client = getOkHttpClient(url); // if (client == null) { diff --git a/src/main/java/com/ynxbd/common/service/MedicalService.java b/src/main/java/com/ynxbd/common/service/MedicalService.java index 905285f..4126ed7 100644 --- a/src/main/java/com/ynxbd/common/service/MedicalService.java +++ b/src/main/java/com/ynxbd/common/service/MedicalService.java @@ -403,7 +403,7 @@ public class MedicalService { /** * [医保]处方下单 */ - public Result createRxOrder(MerchantEnum merchantEnum, Recipe order, PEnum serverEnum, String recipeJson, String payWay) { + public Result createRxOrder(MerchantEnum merchantEnum, Recipe order, PEnum serverEnum, String recipeJson, String payWay, Integer rxType) { String treatNum = order.getTreatNum(); String payOrdId = order.getPayOrdId(); String outTradeNo = order.getOutTradeNo(); @@ -415,6 +415,7 @@ public class MedicalService { // 0:公众号内支付,1:扫码支付 payWay = payWay == null ? "0" : payWay; + rxType = rxType == null ? 0 : rxType; Recipe rxInfo = new RxService().recipeJsonToInfo(treatNum, recipeJson); log.info("[医保][处方]JSON解析 RxInfo={}", rxInfo); @@ -451,6 +452,7 @@ public class MedicalService { String bankTransNo = medOrder.mapGetBankTansNo(); order.setBankTransNo(bankTransNo); order.setPayWay(payWay); + order.setRxType(rxType); // ------------------------------------------- order.setRecipeJson(recipeJsonStr); order.setDeptCode(rxInfo.getDeptCode()); diff --git a/src/main/java/com/ynxbd/common/service/MicroService.java b/src/main/java/com/ynxbd/common/service/MicroService.java index f8f32f8..0babbb9 100644 --- a/src/main/java/com/ynxbd/common/service/MicroService.java +++ b/src/main/java/com/ynxbd/common/service/MicroService.java @@ -1,12 +1,19 @@ package com.ynxbd.common.service; +import cn.hutool.core.util.StrUtil; +import com.ynxbd.common.bean.Patient; +import com.ynxbd.common.bean.pay.Recipe; +import com.ynxbd.common.bean.xk.XKChargeOrRefund; +import com.ynxbd.common.bean.xk.XKCostDetail; import com.ynxbd.common.helper.common.AesMicroHelper; +import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.helper.http.OkHttpHelper; import lombok.extern.slf4j.Slf4j; -import okhttp3.FormBody; -import okhttp3.RequestBody; +import org.apache.commons.lang3.ObjectUtils; import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; /** * @author 李进才 @@ -17,17 +24,100 @@ import java.math.BigDecimal; @Slf4j public class MicroService { - public void OLReg(String openid, BigDecimal totalFee, String outTradeNo, String bankTransNo, String payDate, String payTime) { - RequestBody body = new FormBody.Builder(). - add("callNo", "ol_register"). - add("outTradeNo", AesMicroHelper.encode(outTradeNo)). - add("bankTransNo", AesMicroHelper.encode(bankTransNo)). - add("openid", AesMicroHelper.encode(openid)). - add("totalFee", AesMicroHelper.encode(totalFee.toString())). - add("payDate", payDate). - add("payTime", payTime). - build(); - log.info("[互联网医院在线问诊支付回调] outTradeNo-{}, bankTransNo-{}, openid-{}, totalFee-{}, payDate-{}, payTime-{}", outTradeNo, bankTransNo, openid, totalFee, payDate, payTime); - OkHttpHelper.post("http://127.0.0.1/micro/pay/payNotice", body); + public void notifyOLReg(String openid, BigDecimal totalFee, String outTradeNo, String bankTransNo, String payDate, String payTime) { + try { + log.info("[问诊挂号]回调 outTradeNo-{}, bankTransNo-{}, openid-{}, totalFee-{}, payDate-{}, payTime-{}", outTradeNo, bankTransNo, openid, totalFee, payDate, payTime); + OkHttpHelper.postAsync("http://127.0.0.1/micro/pay/payNotice", map -> { + map.put("callNo", "ol_register"); + map.put("outTradeNo", AesMicroHelper.encode(outTradeNo)); + map.put("bankTransNo", AesMicroHelper.encode(bankTransNo)); + map.put("openid", AesMicroHelper.encode(openid)); + map.put("totalFee", AesMicroHelper.encode(totalFee.toString())); + map.put("payDate", payDate); + map.put("payTime", payTime); + }); + } catch (Exception e) { + log.error("", e); + } + } + + + public void uploadRxFee(List rxList, boolean isNotFailRx, BigDecimal totalFee, boolean isMedIns) { + try { + System.out.println("[监管平台]处方缴费上报..."); + if (rxList.isEmpty()) { + log.warn("[监管平台]缴费处方数量为0"); + return; + } + + Recipe rx = rxList.get(0); + if (rx == null) { + log.warn("[监管平台]处方信息缺失"); + return; + } + String openId = rx.getOpenid(); + String patientId = rx.getPatientId(); + String treatNum = rx.getTreatNum(); + String deptCode = rx.getDeptCode(); + String deptName = rx.getDeptName(); + String bankTransNo = rx.getBankTransNo(); + if (StrUtil.hasBlank(openId, patientId, treatNum, deptCode, deptName, bankTransNo)) { + log.warn("[监管平台]查询HIS患者信息失败 openId={}, patientId={}, treatNum={}, deptCode={}, deptName={}, bankTransNo={}", + openId, patientId, treatNum, deptCode, deptName, bankTransNo); + return; + } + + Patient patient = new PatientService().queryByOpenIdAndEPId(openId, patientId); + if (patient == null) { + patient = new PatientService().queryHisPatientByPatientId(patientId); + if (patient == null) { + log.warn("[监管平台]查询HIS患者信息失败 patientId={}", patientId); + return; + } + } + String idCardNo = patient.getIdCardNo(); + String name = patient.getName(); + String birthdate = patient.getBirthday(); + String sex = patient.getSex(); + + + final String chargeRefundCode = "1"; + List items = new ArrayList<>(); + for (Recipe item : rxList) { + XKCostDetail detail = new XKCostDetail(); + detail.setProjDeno(item.getTradeNo()); + detail.setProjName("处方" + (ObjectUtils.isEmpty(item.getRecipeId()) ? "" : item.getRecipeId())); + detail.setChargeRefundCode(chargeRefundCode); + detail.setStatCatCode("1102"); // 1102:诊查费 + detail.setPinCatCode("9901"); // 9901:其他费 + detail.setIfOutMedIns(isMedIns ? "1" : "0"); // 是否属于门诊医保项目 0、否,1、是 + detail.setProjUnitPrice(item.getPayMoney()); // 项目单价(元) + detail.setProjCnt(new BigDecimal(1)); // 项目数量 + detail.setProjAmount(item.getPayMoney()); // projAmount + items.add(detail); + } + + XKChargeOrRefund xk = new XKChargeOrRefund(); + xk.setIdcardNo(idCardNo); + xk.setName(name); + xk.setBirthDate(birthdate); + xk.setGenderCode("男".equals(sex) ? "1" : "2"); + xk.setVisitNo(treatNum); + xk.setAccountNo(bankTransNo); + xk.setOrderNo(bankTransNo); + xk.setTotalFee(totalFee); + xk.setIndividualPay(totalFee); + xk.setChargeRefundCode(chargeRefundCode); + xk.setPayTypeCode(isMedIns ? "02" : "07"); + xk.setDeptCode(deptCode); + xk.setDeptName(deptName); + xk.setItems(items); + + OkHttpHelper.postAsync("http://127.0.0.1/micro/xk/rxChargeOrRefund", map -> { + map.put("data", AesMicroHelper.encode(JsonHelper.toJsonString(xk))); + }); + } catch (Exception e) { + log.error("", e); + } } } diff --git a/src/main/java/com/ynxbd/common/service/PatientService.java b/src/main/java/com/ynxbd/common/service/PatientService.java index f9277e1..a144fb5 100644 --- a/src/main/java/com/ynxbd/common/service/PatientService.java +++ b/src/main/java/com/ynxbd/common/service/PatientService.java @@ -6,11 +6,9 @@ import com.ynxbd.common.bean.User; import com.ynxbd.common.bean.enums.HCardTypeEnum; import com.ynxbd.common.cache.GmcCacheManager; import com.ynxbd.common.config.HealthCardConfig; -import com.ynxbd.common.config.db.DataBase; import com.ynxbd.common.dao.PatientDao; import com.ynxbd.common.dao.his.HisPatientDao; import com.ynxbd.common.helper.common.*; -import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; @@ -484,25 +482,25 @@ public class PatientService { // } + /** + * [患者]根据患者ID查询信息 + * + * @param patientId 患者id + * @return patient + */ + public Patient queryHisPatientByPatientId(String patientId) throws ServiceException { + return new HisPatientDao().queryHisPatientByPatientId(patientId); + } + + /** * [患者]根据cardNo查询信息 * * @param cardNo cardNo * @return patient */ - public Patient queryPatientByCardNo(String cardNo) throws ServiceException { - if (ObjectUtils.isEmpty(cardNo)) { - throw new ServiceException(ResultEnum.PARAM_IS_DEFECT); - } - JsonResult jsonResult = new HisPatientDao().queryPatientByCardNo(cardNo); - if (!jsonResult.success()) { - throw new ServiceException(jsonResult.getMessage()); - } - Patient patient = jsonResult.dataMapToBean(Patient.class); - if (patient == null) { - throw new ServiceException(ResultEnum.DATA_NOT_FOUND); - } - return patient; + public Patient queryHisPatientByCardNo(String cardNo) throws ServiceException { + return new HisPatientDao().queryHisPatientByCardNo(cardNo); } @@ -514,7 +512,7 @@ public class PatientService { */ public boolean hasHisBindByCardNo(String cardNo) { try { - Patient patient = queryPatientByCardNo(cardNo); + Patient patient = queryHisPatientByCardNo(cardNo); if (patient == null) { return false; } diff --git a/src/main/java/com/ynxbd/common/service/PayService.java b/src/main/java/com/ynxbd/common/service/PayService.java index adb8c80..d5ea562 100644 --- a/src/main/java/com/ynxbd/common/service/PayService.java +++ b/src/main/java/com/ynxbd/common/service/PayService.java @@ -15,6 +15,7 @@ import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.cache.PayCache; +import com.ynxbd.jy.bean.enums.JYBusinessTypeEnum; import com.ynxbd.jy.helper.JYPayHelper; import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxPayHelper; @@ -87,7 +88,7 @@ public class PayService { break; case OL_REG: - new MicroService().OLReg(openid, totalFee, outTradeNo, bankTransNo, payDate, payTime); + new MicroService().notifyOLReg(openid, totalFee, outTradeNo, bankTransNo, payDate, payTime); break; case PEIS_RESERVE: @@ -297,6 +298,9 @@ public class PayService { } return BCMHelper.refund(outTradeNo, outRefundNo, tradeDateStr, refundMoney, refundDesc); + case JY: + log.info("【京颐退款】outTradeNo={}, outRefundNo={}, tradeDate={}", outTradeNo, outRefundNo, tradeDate); + return JYPayHelper.refundPayOrder(JYBusinessTypeEnum.B102, new ReqOrder(), outRefundNo, refundMoney, outTradeNo, null, null); default: break; } @@ -562,7 +566,7 @@ public class PayService { return BCMHelper.createOrder(merchantEnum, title, bizTradeNo, totalFee, pEnum.CODE); } else if (MerchantEnum.JY.equals(merchantEnum)) { // 京颐 - return JYPayHelper.createOrder(merchantEnum, title, bizTradeNo, totalFee, pEnum.CODE, ip, payOpenId, msgOpenId, new ReqOrder()); + return JYPayHelper.createOrder(merchantEnum, title, bizTradeNo, totalFee, pEnum, ip, payOpenId, msgOpenId, new ReqOrder()); } return null; } diff --git a/src/main/java/com/ynxbd/common/service/RxService.java b/src/main/java/com/ynxbd/common/service/RxService.java index e7d4ffe..a91a606 100644 --- a/src/main/java/com/ynxbd/common/service/RxService.java +++ b/src/main/java/com/ynxbd/common/service/RxService.java @@ -2,10 +2,7 @@ package com.ynxbd.common.service; import com.alibaba.fastjson.JSONObject; import com.ynxbd.common.action.pay.PEnum; -import com.ynxbd.common.bean.ConfigSelfHelp; -import com.ynxbd.common.bean.HisRecipe; -import com.ynxbd.common.bean.SelfHelpCount; -import com.ynxbd.common.bean.StandardPrice; +import com.ynxbd.common.bean.*; import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.bean.pay.ApiPrepayResp; import com.ynxbd.common.bean.pay.Order; @@ -96,7 +93,7 @@ public class RxService { * @param treatNum 门诊号 * @return 是否完成操作 */ - public Result medInsPrepay(MerchantEnum merchantEnum, String payOpenId, String openid, String patientId, String treatNum, String totalFee, String recipeJson, String payWay, Integer awaitSecond, boolean isHttps) { + public Result medInsPrepay(MerchantEnum merchantEnum, String payOpenId, String openid, String patientId, String treatNum, String totalFee, String recipeJson, String payWay, Integer rxType, Integer awaitSecond, boolean isHttps) { try { Result result = PayService.isPaymentPermittedByTime(); if (result != null) { @@ -129,7 +126,7 @@ public class RxService { if ("0".equals(totalFee)) { String bizTradeNo = merchantEnum.createBizTradeNo(); // 订单信息预存 - if (!rxService.saveRxData(merchantEnum, payOpenId, openid, recipeJson, payWay, patientId, treatNum, totalFee, new ApiPrepayResp(bizTradeNo))) { + if (!rxService.saveRxData(merchantEnum, payOpenId, openid, recipeJson, payWay, rxType, patientId, treatNum, totalFee, new ApiPrepayResp(bizTradeNo))) { log.info("{} [处方支付]预存支付信息失败 patientId={}", merchantEnum.NAME, patientId); return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); } @@ -228,8 +225,8 @@ public class RxService { * @param treatNum 门诊号 * @return 是否完成操作 */ - public boolean saveRxData(MerchantEnum merchantEnum, String payOpenId, String openid, String recipeJson, String payWay, String patientId, String treatNum, String totalFee, ApiPrepayResp prepayResp) throws ServiceException { - log.info("{}[处方支付]预存信息 patientId={}, treatNum={}, recipeJson={}", merchantEnum.NAME, patientId, treatNum, recipeJson); + public boolean saveRxData(MerchantEnum merchantEnum, String payOpenId, String openid, String recipeJson, String payWay, Integer rxType, String patientId, String treatNum, String totalFee, ApiPrepayResp prepayResp) throws ServiceException { + log.info("{}[处方支付]预存信息 patientId={}, treatNum={}, rxType={}, recipeJson={}", merchantEnum.NAME, patientId, treatNum, rxType, recipeJson); List rxList = JsonHelper.parseArray(recipeJson, Recipe.class); if (rxList == null || rxList.isEmpty()) { throw new ServiceException("[处方支付]勾选处方数量为0 或 数据转换失败"); @@ -244,6 +241,7 @@ public class RxService { RxDao rxDao = new RxDao(); // 0:公众号内支付,1:扫码支付 payWay = payWay == null ? "0" : payWay; + rxType = rxType == null ? 0 : rxType; for (Recipe rxItem : rxList) { if (ObjectUtils.isEmpty(rxItem.getRecipeId()) || ObjectUtils.isEmpty(rxItem.getRecipeFee())) { @@ -258,6 +256,7 @@ public class RxService { rxItem.setBizTradeNo(bizTradeNo); rxItem.setMixTradeNo(mixTradeNo); rxItem.setPayWay(payWay); + rxItem.setRxType(rxType); // recipe.setTradeNo(CodeHelper.getHisTradeNo()); // 本次his交易流水号 rxItem.setTradeNo(null); // 本次his交易流水号 rxItem.setTotalFee(new BigDecimal(totalFee)); @@ -304,10 +303,10 @@ public class RxService { PayService.saveOrderNo(PEnum.RECIPE, outTradeNo, openid, payInfo, null); } - List recipeList = rxDao.selectListByOutTradeNo(outTradeNo); - if (!rxDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, recipeList)) { + List rxList = rxDao.selectListByOutTradeNo(outTradeNo); + if (!rxDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, rxList)) { log.info("{} [处方]更新商户信息失败(1) outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); - if (!rxDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, recipeList)) { + if (!rxDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, rxList)) { log.info("{} [处方]更新商户信息失败(2) outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); return false; } @@ -315,7 +314,7 @@ public class RxService { // 订单金额验证 BigDecimal rxTotalFee = BigDecimal.ZERO; - for (Recipe recipe : recipeList) { + for (Recipe recipe : rxList) { rxTotalFee = rxTotalFee.add(recipe.getPayMoney()); } @@ -331,7 +330,7 @@ public class RxService { // HIS缴费 String patientId = null; Recipe rxInfo; - for (Recipe rxItem : recipeList) { + for (Recipe rxItem : rxList) { patientId = rxItem.getPatientId(); rxItem.setBankTransNo(bankTransNo); // HIS处方缴费 @@ -346,7 +345,7 @@ public class RxService { if (rxItem.getTreatNum().contains("P-")) { // 体检缴费失败的所有费用进行退回 if (rxInfo.isRefund()) { - failedList = recipeList; + failedList = rxList; for (Recipe failed : failedList) { failed.setErrorCode(rxInfo.getErrorCode()); failed.setErrorMsg(rxInfo.getErrorMsg()); @@ -386,13 +385,17 @@ public class RxService { } } - String tip = String.format("共计缴费处方单数:%s,失败数:%s,超时数:%s", recipeList.size(), (failedList.size() - outTimeList.size()), outTimeList.size()); + String tip = String.format("共计缴费处方单数:%s,失败数:%s,超时数:%s", rxList.size(), (failedList.size() - outTimeList.size()), outTimeList.size()); log.info("{} [处方]{}", merchantEnum.NAME, tip); if (WeChatConfig.APP_ID.equals(HospConfigEnum.红河州第一人民医院.WX_APP_ID)) { TZReserveConfig.reserveRun(patientId); // 天助医技预约 } + if (MerchantEnum.JY.equals(merchantEnum)) { + new MicroService().uploadRxFee(rxList, failedList.isEmpty(), new BigDecimal(totalFee), false); + } + new HealthUploadService().rxReportHISData(merchantEnum, openid, patientId); return true; } diff --git a/src/main/java/com/ynxbd/jy/bean/JYPayNotify.java b/src/main/java/com/ynxbd/jy/bean/JYPayNotify.java index 15a940d..fabf9aa 100644 --- a/src/main/java/com/ynxbd/jy/bean/JYPayNotify.java +++ b/src/main/java/com/ynxbd/jy/bean/JYPayNotify.java @@ -55,8 +55,12 @@ public class JYPayNotify { // 退款==================================================== // 商户退款流水号,由应用端(应用方、接入方)生成,要求唯一。对应入参 private String refundTransId; + // 退费时间-20260928012108 + private String refundTime; // 退款金额,精确到分,例如100 private Long refundAmt; + // 退费状态 + private String refundState; // 交易状态,退款交易状态,详见数据字典#交易流水状态 private String tranStatus; // 交易代码,002 撤销 004 退费 005 冲正,详细请参考数据字典#交易代码 diff --git a/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java b/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java index d0aaf0d..78f5ce8 100644 --- a/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java +++ b/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java @@ -1,8 +1,11 @@ package com.ynxbd.jy.helper; import com.alibaba.fastjson.JSONObject; +import com.ynxbd.common.action.pay.JYPSEnum; +import com.ynxbd.common.action.pay.PEnum; import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.bean.pay.ApiPayNotify; +import com.ynxbd.common.bean.pay.Order; import com.ynxbd.common.bean.pay.ReqOrder; import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.helper.common.JsonHelper; @@ -52,31 +55,31 @@ public class JYPayHelper { * @param title 商品标题 * @param totalFee 订单金额 * @param merOrderNum 应用商户订单号 - * @param notifyType 回调类型 + * @param pEnum 业务类型 * @param ip ip地址 * @param payOpenId 用于下单的openId * @param msgOpenId 用于推送的openId * @return 成功返回 json, 否则返回null */ - public static JSONObject createOrder(MerchantEnum merchantEnum, String title, String merOrderNum, String totalFee, String notifyType, String ip, String payOpenId, String msgOpenId, ReqOrder reqOrder) { + public static JSONObject createOrder(MerchantEnum merchantEnum, String title, String merOrderNum, String totalFee, PEnum pEnum, String ip, String payOpenId, String msgOpenId, ReqOrder reqOrder) { try { + String notifyType = pEnum.CODE; + + JYPSEnum jyEnum = JYPSEnum.findEnum(pEnum); if (ObjectUtils.isEmpty(payOpenId) || ObjectUtils.isEmpty(merOrderNum) || merchantEnum == null || totalFee == null || notifyType == null) { log.error("【京硕】预下单参数缺失"); return null; } - String cents; - try { - cents = new BigDecimal(totalFee).movePointRight(2).toString(); // 金额转换=>单位分 - } catch (Exception e) { - log.error("【京硕】预下单金额转换异常:", e); + int orderAmt = new BigDecimal(totalFee).movePointRight(2).intValue(); // 金额转换=>单位分 + if (orderAmt == 0) { + log.error("【京硕】订单金额转换异常,或金额为0"); return null; } log.info("【京硕】预下单 {},{},{},{},{}", title, merOrderNum, totalFee, ip, merchantEnum.NOTIFY_URL); - JYOrder jyOrder = reqOrder.jyOrder; Map params = new HashMap<>(); params.put("openId", payOpenId); params.put("hospitalId", JYPayConfig.HOSP_ID); // 医院ID @@ -86,28 +89,28 @@ public class JYPayHelper { params.put("hisOrderNum", null); // HIS订单号:可以为发票号[该接口若不传,在业务完成后调用2.1.6接口] params.put("hisTransNum", null); // HIS流水号:可以为发票号[该接口若不传,在业务完成后调用2.1.6接口] // 金额 - params.put("orderAmt", cents); // 交易金额:只接收整数,单位:分,例如100表示壹圆整;支付宝医保支付传总金额 + params.put("orderAmt", Integer.toString(orderAmt)); // 交易金额:只接收整数,单位:分,例如100表示壹圆整;支付宝医保支付传总金额 - params.put("orderType", jyOrder.orderTypeEnum.CODE); // 如:001:挂号费 002:医药费; + params.put("orderType", jyEnum.ORDER_TYPE.CODE); // 如:001:挂号费 002:医药费; params.put("backURL", WeChatConfig.getBaseURL() + merchantEnum.NOTIFY_URL + "?notifyType=" + notifyType); // 商户异步回调地址:后台发起异步回调地址, 扫码枪支付方式无需回调的可以不 params.put("backParamsType", "key-value"); // 商户异步回调入参格式:后台发起异步回调时参数格式,取值有:key-value和json,默认值是key-value。 params.put("payType", "WX_PUBLIC"); // 如:UPOP_APP, UPOP_WEB;详见附录5.1[微信公众号支付(WX_PUBLIC)] - params.put("bussinessType", jyOrder.businessTypeEnum.CODE); // 业务类型:综合支付对应用权限控制是否必传 最大不超过4位,详见数据字典5.2 该接口若不传,需要调用2.1.6接口再次更新 - params.put("patientName", reqOrder.getPatientName()); // 微信医保支付必传。其余支付方式若该接口若不传,需要调用2.1.6接口再次更新 - params.put("patientGender", reqOrder.getPatientGender()); // 患者性别。综合支付对应用权限控制是否必传 1男 2女 9其他 最大不超过4位 该接口若不传,需要调用2.1.6接口再次更新 - params.put("patientAge", reqOrder.getPatientAge()); // 患者年龄。综合支付对应用权限控制是否必传 该接口若不传,需要调用2.1.6接口再次更新 - params.put("patientIdNo", reqOrder.getPatientIdCardNo()); // 微信医保支付必传。其余支付方式若该接口若不传,需要调用2.1.6接口再次更新 - params.put("patientPhoneNumber", reqOrder.getPatientTel()); // 综合支付对应用权限控制是否必传 最大不超过16位 该接口若不传,需要调用2.1.6接口再次更新 - params.put("patientId", reqOrder.getPatientId()); // 患者ID:综合支付对应用权限控制是否必传 最大不超过32位 该接口若不传,需要调用2.1.6接口再次更新 - params.put("patientCardNo", reqOrder.getPatientId()); // 患者卡号:综合支付对应用权限控制是否必传 最大不超过32位该接口若不传,需要调用2.1.6接口再次更新 - params.put("clinicNo", reqOrder.getTreatNum()); // 门诊号:综合支付对应用权限控制是否必传 最大不超过32位该接口若不传,需要调用2.1.6接口再次更新 - params.put("inpNo", reqOrder.getTreatNum()); // 住院号:综合支付对应用权限控制是否必传 最大不超过32位该接口若不传,需要调用2.1.6接口再次更新 - params.put("hisTransDoneTime", null); // HIS业务完成时间:综合支付对应用权限控制是否必传 YYYY-MM-DD HH:MM:SS 该接口若不传,需要调用2.1.6接口再次更新 - params.put("hisOperatorNo", jyOrder.getHisOperatorNo()); // HIS操作员编号:综合支付对应用权限控制是否必传HIS操作员编号和HIS操作员姓名必须成对出现该接口若不传,需要调用2.1.6接口再次更新 - params.put("hisOperatorName", jyOrder.getHisOperatorName()); // HIS操作员姓名:综合支付对应用权限控制是否必传 HIS操作员编号和HIS操作员姓名必须成对出现 该接口若不传,需要调用2.1.6接口再次更新 - params.put("receiptNo", null); // 综合支付对应用权限控制是否必传最大不超过200位 该接口若不传,需要调用2.1.6接口再次更新 - params.put("remarks", ""); // 备注 建行渠道格式为json,参考样式:{"REMARK1":"REM1","REMARK2":"REM2"} 农行渠道参考样式:{"TerminalNo":"1234567"} + params.put("bussinessType", jyEnum.BUSINESS_TYPE.CODE); // 业务类型:综合支付对应用权限控制是否必传 最大不超过4位,详见数据字典5.2 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("patientName", reqOrder.getPatientName()); // 微信医保支付必传。其余支付方式若该接口若不传,需要调用2.1.6接口再次更新 +// params.put("patientGender", reqOrder.getPatientGender()); // 患者性别。综合支付对应用权限控制是否必传 1男 2女 9其他 最大不超过4位 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("patientAge", reqOrder.getPatientAge()); // 患者年龄。综合支付对应用权限控制是否必传 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("patientIdNo", reqOrder.getPatientIdCardNo()); // 微信医保支付必传。其余支付方式若该接口若不传,需要调用2.1.6接口再次更新 +// params.put("patientPhoneNumber", reqOrder.getPatientTel()); // 综合支付对应用权限控制是否必传 最大不超过16位 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("patientId", reqOrder.getPatientId()); // 患者ID:综合支付对应用权限控制是否必传 最大不超过32位 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("patientCardNo", reqOrder.getPatientId()); // 患者卡号:综合支付对应用权限控制是否必传 最大不超过32位该接口若不传,需要调用2.1.6接口再次更新 +// params.put("clinicNo", reqOrder.getTreatNum()); // 门诊号:综合支付对应用权限控制是否必传 最大不超过32位该接口若不传,需要调用2.1.6接口再次更新 +// params.put("inpNo", reqOrder.getTreatNum()); // 住院号:综合支付对应用权限控制是否必传 最大不超过32位该接口若不传,需要调用2.1.6接口再次更新 +// params.put("hisTransDoneTime", null); // HIS业务完成时间:综合支付对应用权限控制是否必传 YYYY-MM-DD HH:MM:SS 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("hisOperatorNo", null); // HIS操作员编号:综合支付对应用权限控制是否必传HIS操作员编号和HIS操作员姓名必须成对出现该接口若不传,需要调用2.1.6接口再次更新 +// params.put("hisOperatorName", null); // HIS操作员姓名:综合支付对应用权限控制是否必传 HIS操作员编号和HIS操作员姓名必须成对出现 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("receiptNo", null); // 综合支付对应用权限控制是否必传最大不超过200位 该接口若不传,需要调用2.1.6接口再次更新 +// params.put("remarks", ""); // 备注 建行渠道格式为json,参考样式:{"REMARK1":"REM1","REMARK2":"REM2"} 农行渠道参考样式:{"TerminalNo":"1234567"} // 医保支付====================================== // params.put("orderTotalAmt", cents); // orderTotalAmt:微信医保支付必传,有社保交易数据时,订单总金额=自费实际金额+社保金额+减免金额 @@ -192,29 +195,28 @@ public class JYPayHelper { * * @return 成功返回 json, 否则返回null */ - public static JSONObject refundPayOrder(JYBusinessTypeEnum businessTypeEnum, ReqOrder patient, String outRefundNo, BigDecimal refundFee, String outTradeNo, String bankMerchantNo, String tradeNo) { + public static Order refundPayOrder(JYBusinessTypeEnum businessTypeEnum, ReqOrder patient, String outRefundNo, BigDecimal refundFee, String outTradeNo, String bankMerchantNo, String tradeNo) { + Order order = new Order(); try { log.info("【京硕】退款申请 {},{},{},{}", outTradeNo, bankMerchantNo, tradeNo, refundFee); if (ObjectUtils.isEmpty(outTradeNo) && ObjectUtils.isEmpty(bankMerchantNo) && ObjectUtils.isEmpty(tradeNo)) { - return null; + order.setErrorMsg("【京硕】退款参数缺失"); + order.setRefundResult("退款参数缺失"); + return order; } - String refundCents; - try { - if (refundFee == null) { - return null; - } - refundCents = refundFee.movePointRight(2).toString(); // 金额转换=>单位分 - } catch (Exception e) { - log.info("【京硕】退款申请-金额转换异常:", e); - return null; + int refundAmt = refundFee.movePointRight(2).intValue(); // 单位分 + if (refundAmt == 0) { + order.setErrorMsg("【京硕】退费金额转换异常,或退费金额为0"); + order.setRefundResult("退费金额转换异常,或退费金额为0"); + return order; } Map params = new HashMap<>(); params.put("applicationId", JYPayConfig.APPLICATION_ID); params.put("merchantId", JYPayConfig.MERCHANT_ID); - params.put("refundAmt", refundCents); // 微信医保和支付宝医保只支持全部退款(支付宝医保为总金额)。只接收整数,单位:分,例如100表示壹圆整; + params.put("refundAmt", Integer.toString(refundAmt)); // 微信医保和支付宝医保只支持全部退款(支付宝医保为总金额)。只接收整数,单位:分,例如100表示壹圆整; params.put("refundTransId", outRefundNo); // 由应用方生成的退款流水号,要求唯一。同一笔退款流水若重复发送,该流水号不能变,否则平台会认为发起一笔新的退款流水。 params.put("orderId", outTradeNo); // 支付平台订单号 params.put("merOrderNum", bankMerchantNo); // 应用方自己生成的订单唯一标识[BankMerchantNo] @@ -247,7 +249,9 @@ public class JYPayHelper { String signValue = createSign(params); if (signValue == null) { - return null; + order.setErrorMsg("【京硕】签名错误"); + order.setRefundResult("签名错误"); + return order; } params.put("signValue", signValue); // 数字签名:由接入方生成的签名,支付平台根据该字段对入参进行验签;签名生成规则参考4加签验签规则 @@ -256,13 +260,20 @@ public class JYPayHelper { log.info("【京硕】退款申请-响应-{}", JsonHelper.toJsonString(result)); if (!result.isSuccess()) { log.error("【京硕】退款申请-失败:{}", result.getMessage()); - return null; + order.setErrorCode(result.getCode()); + order.setErrorMsg(result.getMessage()); + order.setRefundResult(result.getMessage()); + return order; } - return result.getData(); +// JSONObject data = result.getData(); + order.setRefundResult("OK"); + order.setSuccess(true); // 操作成功标识 + return order; } catch (Exception e) { log.error("【京硕】退款申请异常信息:", e); + order.setErrorMsg("【京硕】" + e.getMessage()); + return order; } - return null; } /** @@ -391,18 +402,19 @@ public class JYPayHelper { return Base64.getEncoder().encodeToString(signature.sign()); } - public static ApiPayNotify jyPayNotify(JYPayNotify notifyInfo, String attach) { + public static ApiPayNotify jyPayNotify(Map params, String attach) { + JYPayNotify notifyInfo = JsonHelper.parseObject(JsonHelper.toJsonString(params), JYPayNotify.class); + ApiPayNotify data = new ApiPayNotify(); data.setOpenId(notifyInfo.getOpenId()); BigDecimal totalFeeCent = new BigDecimal(notifyInfo.getOrderAmt()); - Map dateMap = getDateMap(notifyInfo.getPaymentTime()); - data.setPayDate(dateMap.get(WxSignHelper.DATE_KEY)); - data.setPayTime(dateMap.get(WxSignHelper.TIME_KEY)); - - data.setPayDate(dateMap.get(WxSignHelper.DATE_KEY)); - data.setPayTime(dateMap.get(WxSignHelper.TIME_KEY)); + if (!ObjectUtils.isEmpty(notifyInfo.getPaymentTime())) { + Map dateMap = getDateMap(notifyInfo.getPaymentTime()); + data.setPayDate(dateMap.get(DATE_KEY)); + data.setPayTime(dateMap.get(TIME_KEY)); + } data.setMerchantEnum(MerchantEnum.JY); data.setOpenId(notifyInfo.getOpenId()); @@ -410,6 +422,7 @@ public class JYPayHelper { data.setBizTradeNo(notifyInfo.getMerchantNo()); data.setTransactionId(notifyInfo.getFinalTransNo()); data.setRefundTransId(notifyInfo.getRefundTransId()); + data.setRefundTime(notifyInfo.getRefundTime()); data.setTotalFee(totalFeeCent.movePointLeft(2)); data.setPayInfo(null);