package com.ywt.alipaympapi.service.impl; import com.alipay.api.domain.AlipayTradeCreateModel; import com.alipay.api.domain.AlipayTradeQueryModel; import com.alipay.api.response.AlipayTradeCreateResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import com.ywt.alipaympapi.core.utils.*; import com.ywt.alipaympapi.face.IPayFace; import com.ywt.alipaympapi.models.Constants; import com.ywt.alipaympapi.models.enums.PaymentStatusEnum; import com.ywt.core.exception.AppMessageException; import com.ywt.gapi.Result; import com.ywt.gapi.ResultCode; import com.ywt.gapi.drug.GetOneKeyRegListRequest; import com.ywt.gapi.drug.GetOneKeyRegListResponse; import com.ywt.gapi.order.*; import com.ywt.gapi.order.OutpatientOrder; import com.ywt.gapi.ordercenter.*; import com.ywt.gapi.system.GetConfigByTypeRequest; import com.ywt.gapi.system.GetConfigByTypeResponse; import com.ywt.gapi.taihe.outpaitent.*; import com.ywt.gapi.taihe.outpaitent.BaseResult; import com.ywt.gapi.third.taihe.*; import com.ywt.gapi.third.taihe.GetOutpatientListRequest; import com.ywt.gapi.third.taihe.GetOutpatientListResponse; import com.ywt.gapi.wx_ins_pay.MarkOpOrderDeletedRequest; import com.ywt.gapi.wx_ins_pay.MarkOpOrderDeletedResponse; import com.ywt.gapi.wx_ins_pay.WxInsPayServiceGrpc; import com.ywt.model.PageVO; import com.ywt.model.Pagination; import com.ywt.request.pay.*; import com.ywt.response.inpatient.DepositTradeResponseData; import com.ywt.response.pay.*; import com.ywt.alipaympapi.service.IsvPayService; import com.ywt.response.report.QueryReportListResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; @Slf4j @Service public class IsvPayServiceImpl implements IsvPayService { @Resource private IPayFace payFace; public static final int TYPE_UNPAID_WX = 1; private static final int TYPE_PAID_WX = 2; public static final int TYPE_UNPAID_ZFB = 0; private static final int TYPE_PAID_ZFB = 1; @Autowired private TaiheServiceGrpc.TaiheServiceBlockingStub taiheServiceBlockingStub; @Autowired private TaiheOutpatientServiceGrpc.TaiheOutpatientServiceBlockingStub taiheOutpatientServiceBlockingStub; @Autowired private com.ywt.gapi.drug.DrugServiceGrpc.DrugServiceBlockingStub drugServiceBlockingStub; @Autowired private OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub; @Autowired private OrderCenterServiceGrpc.OrderCenterServiceBlockingStub orderCenterServiceBlockingStub; @Autowired private WxInsPayServiceGrpc.WxInsPayServiceBlockingStub wxInsPayServiceBlockingStub; // 商家订单号获取 @Override public TradeNoResponseData queryTradeNo(OutTradeNoRequest request) throws Exception { int orderId = Integer.parseInt(request.getOrderId()); if (orderId <= 0) { throw new AppMessageException("该订单不存在"); } int userId = Integer.parseInt(request.getUserId()); int amount = BizUtil.yuan2Cent(request.getAmount()); CreateAlipayOrderResponse response = orderCenterServiceBlockingStub.createAlipayOrder(CreateAlipayOrderRequest.newBuilder() .setBody("预约挂号") .setAlipayUid(request.getAlipayUid()) .setOrderId(orderId) .setOrderNo("") .setAmount(amount) .setUserId(userId) .setTerminal(ContextHelper.getCurrentTerminalWrapped()) .build()); if (response.getCode() != ResultCode.SUCCEED_VALUE) throw new AppMessageException("支付宝下单:" + response.getInfo()); TradeNoResponseData data = new TradeNoResponseData(); data.setOrderId(orderId); data.setOutTradeNo(response.getOrderNo()); data.setTradeNo(response.getTradeNo()); return data; } @Override public TradeResultResponseData informTradeResult(TradeResultRequest request) { TradeResultResponseData data = new TradeResultResponseData(); AlipayTradeQueryModel alipayTradeQueryModel = new AlipayTradeQueryModel(); alipayTradeQueryModel.setTradeNo(request.getTradeNo()); AlipayTradeQueryResponse response = payFace.tradeQuery(request.getAppId(), alipayTradeQueryModel); if ("TRADE_SUCCESS".equals(response.getTradeStatus())) { data.setStatus("TRADE_SUCCESS"); } return data; } @Override public PayDetailResponseData queryPayDetail(PayDetailRequest request) throws Exception { int userId = ContextHelper.getCurrentUserIdWrapped(); int hospitalId = BizUtil.getCurrentHospitalId(); if (Checker.isNone(request.getStatus())) { throw new RuntimeException("订单状态不能为空"); } if (request.getStatus() == TYPE_UNPAID_ZFB) { PayDetailResponseData da = new PayDetailResponseData(); da.setDeptName(Checker.getStringValue(request.getDeptName())); if(!Checker.isNone(request.getAge()) && request.getAge() > 0){ da.setAge(request.getAge()); } da.setSex(Checker.getStringValue(request.getSex())); da.setStatus(request.getStatus()); da.setDoctorName(Checker.getStringValue(request.getDoctorName())); da.setDoctorCode(Checker.getStringValue(request.getDoctorCode())); da.setHisClinicCode(Checker.getStringValue(request.getHisClinicCode())); da.setPrescribeDate(Checker.getStringValue(request.getPrescribeDate())); da.setTotal(request.getTotal()); da.setUserName(Checker.getStringValue(request.getName())); da.setName(Checker.getStringValue(request.getName())); da.setHisOrderNo(Checker.getStringValue(request.getHisOrderNo())); da.setAmount(Checker.getStringValue(request.getAmount())); da.setCreateTime(Checker.getStringValue(request.getPrescribeDate())); da.setHisPatientId(request.getHisPatientId()); return da; } if (Checker.isNone(request.getInvoiceNo()) && Checker.isNone(request.getOutTradeNo())) { throw new RuntimeException("订单发票号不存在"); } List list = new LinkedList<>(); PayDetailResponseData da = new PayDetailResponseData(); String hisPatientId = Checker.getStringValue(request.getHisPatientId()); switch (hospitalId) { default: case Constants.HOSPITAL_ID_NFYYBYFY: // 白云从 HIS 接口获取门诊缴费详情 String invoiceNo = Checker.getStringValue(request.getInvoiceNo()); CheckUtil.ensureNotEmpty(invoiceNo, "发票号不能为空"); CheckUtil.ensureNotEmpty(hisPatientId, "HIS 病人 id 不能为空"); // 根据 his_patient_id 获取诊疗卡信息 String pName = ""; Integer pAge = 0; String pGender = ""; String cardNum = ""; GetMedicalCardInfoByPatientIdRequest gResp = GetMedicalCardInfoByPatientIdRequest.newBuilder() .setHisPatientId(hisPatientId) .setHospitalId(hospitalId) .setUserId(userId) .build(); GetMedicalCardInfoByPatientIdResponse gmcResp = taiheOutpatientServiceBlockingStub.getMedicalCardInfoByPatientId(gResp); if (gmcResp.getCode() == ResultCode.SUCCEED_VALUE) { pName = gmcResp.getPatientName(); pAge = getPatientAgeSafely(gmcResp.getIdNo(), gmcResp.getBirthday()); pGender = IdCardUtil.getSex(gmcResp.getIdNo()); cardNum = Checker.getStringValue(gmcResp.getCardNo()); } GetPaymentDetailResponse response2 = taiheServiceBlockingStub.getPaymentDetail(GetPaymentDetailRequest.newBuilder() .setHospitalId(hospitalId) .setInvoiceNo(invoiceNo) .setHisPatientId(hisPatientId) .setType("2") .build()); if (response2.getCode() != ResultCode.SUCCEED_VALUE) throw new RuntimeException(response2.getMsg()); if (!Checker.isNone(response2.getDetailList())) { list = response2.getDetailList().stream() .map(i -> { OrderItem it = new OrderItem(); it.setItemName(i.getItemName()); it.setAmount(String.format("%.2f", i.getItemPrice() / 100d)); it.setItemNum(String.valueOf(i.getItemNumber())); return it; }) .collect(Collectors.toList()); } da.setAge(Checker.getIntegerValue(pAge)); da.setUserName(Checker.getStringValue(pName)); da.setSex(pGender); da.setPayDate(request.getDate()); da.setOrderItems(list); da.setCardNum(cardNum); da.setOrderId(""); da.setTotal(request.getTotal()); da.setStatus(request.getStatus()); da.setAmount(request.getAmount()); da.setHisPatientId(request.getHisPatientId()); break; } return da; } @Override public PageVO queryPayHistory(PayHistoryRequest request) throws Exception { List list = new ArrayList<>(); int pageIndex = request.getPageIndex(); int pageSize = request.getPageSize(); int total = 0; if (Checker.isNone(request.getStatus())) { throw new AppMessageException("订单状态不能为空"); } int status = Integer.parseInt(Checker.getStringValue(request.getStatus())); if (Checker.isNone(request.getHisPatientId())) { throw new AppMessageException("hisPatientI不能为空"); } String hisPatientId = Checker.getStringValue(request.getHisPatientId()); int userId = ContextHelper.getCurrentUserIdWrapped(); String pName = ""; int pAge = 0; String pGender = ""; int hospitalId = BizUtil.getCurrentHospitalId(); GetMedicalCardInfoByPatientIdRequest gResp = GetMedicalCardInfoByPatientIdRequest.newBuilder() .setHisPatientId(hisPatientId) .setHospitalId(hospitalId) .setUserId(userId) .build(); GetMedicalCardInfoByPatientIdResponse resp = taiheOutpatientServiceBlockingStub.getMedicalCardInfoByPatientId(gResp); if (resp.getCode() == ResultCode.SUCCEED_VALUE) { pName = resp.getPatientName(); pAge = getPatientAgeSafely(resp.getIdNo(), resp.getBirthday()); pGender = IdCardUtil.getSex(resp.getIdNo()); } switch (status) { case TYPE_UNPAID_ZFB: // 待缴费列表从 HIS 获取数据 GetOutpatientListRequest req = GetOutpatientListRequest.newBuilder() .setPatientId(hisPatientId) .setType(TYPE_UNPAID_WX) .setHospitalId(hospitalId) .build(); GetOutpatientListResponse result = taiheServiceBlockingStub.getOutpatientList(req); if (result.getCode() != ResultCode.SUCCEED_VALUE) { throw new RuntimeException(result.getMsg()); } List> lst = new LinkedList<>(); Map map; List paymentItems = result.getPaymentList(); if (!Checker.isNone(paymentItems)) { // 过滤处方门诊缴费单 GetOneKeyRegListRequest getOneKeyRegListRequest = GetOneKeyRegListRequest.newBuilder() .setUserId(userId) .build(); GetOneKeyRegListResponse getOneKeyRegListResponse = drugServiceBlockingStub.getOneKeyRegList(getOneKeyRegListRequest); List clinicCodes = getOneKeyRegListResponse.getCode() == ResultCode.SUCCEED_VALUE ? getOneKeyRegListResponse.getClinicCodeList() : new LinkedList<>(); List payItems = paymentItems; if (!clinicCodes.isEmpty()) { payItems = paymentItems.stream() .filter(paymentItem -> !clinicCodes.contains(paymentItem.getClinicCode())) .collect(Collectors.toList()); } total = payItems.size(); for (PaymentItem payItem : payItems) { PayHistoryResponseData data = new PayHistoryResponseData(); data.setStatus(status); data.setTitle(""); data.setHisOrderNo(payItem.getHisOrdNum()); data.setOrderId(payItem.getOrderId()); data.setDeptName(payItem.getDeptName()); data.setPrescribeDate(payItem.getPrescriptionDate()); data.setName(resp.getPatientName()); data.setTotal(payItem.getTotalFee()); data.setAmount(String.format("%.2f", payItem.getTotalFee() / 100d)); data.setTradeNo(""); //Todo data.setOutTradeNo("");//Todo data.setIdNum("");//Todo data.setInvoiceNo(Checker.getStringValue(payItem.getInvoiceNo())); data.setHisPatientId(hisPatientId); data.setAge(Checker.getIntegerValue(pAge)); data.setSex(pGender); data.setDoctorName(payItem.getDoctorName()); data.setDoctorCode(payItem.getDoctorCode()); data.setHisClinicCode(payItem.getClinicCode()); data.setType(0); list.add(data); // map.put("hisClinicCode", payItem.getClinicCode()); // map.put("hisOrderNo", payItem.getHisOrdNum()); // map.put("patientName", pName); // map.put("orderInsType", payItem.getOrderInsType()); // map.put("patientAge", pAge); // map.put("patientSex", pGender); // map.put("doctorCode", payItem.getDoctorCode()); List detailItems = payItem.getItemListList(); List> items = new LinkedList<>(); for (PayDetailItem detailItem : detailItems) { Map d = new HashMap<>(); d.put("name", detailItem.getItemName()); d.put("price", detailItem.getItemPrice()); d.put("code", detailItem.getItemCode()); d.put("number", detailItem.getItemNumber()); d.put("spec", detailItem.getItemSpec()); d.put("unit", detailItem.getItemUnit()); d.put("totalFee", detailItem.getItemTotalFee()); items.add(d); } // map.put("detailItems", items); // lst.add(map); // 保存门诊缴费明细到数据库 SaveOutpatientOrderDetailsRequest sReq = SaveOutpatientOrderDetailsRequest.newBuilder() .setHisOrderNo(payItem.getHisOrdNum()) .addAllDetail(payItem.getItemListList().stream() .map(i -> OutpatientOrderDetail.newBuilder() .setItemName(i.getItemName()) .setItemPrice(i.getItemPrice()) .setItemCode(i.getItemCode()) .setItemNumber(i.getItemNumber()) .setItemSpec(i.getItemSpec()) .setItemUnit(i.getItemUnit()) .setItemTotalFee(i.getItemTotalFee()) .build()).collect(Collectors.toList())) .build(); BaseResult baseResult = taiheOutpatientServiceBlockingStub.saveOutpatientOrderDetails(sReq); if (baseResult.getCode() != ResultCode.SUCCEED_VALUE) { throw new RuntimeException("保存门诊缴费明细失败"); // logger.error("保存门诊缴费明细失败,hisOrderNo : {}", payItem.getHisOrdNum()); } } } break; case TYPE_PAID_ZFB: switch (hospitalId) { default: case Constants.HOSPITAL_ID_NFYYBYFY: // v1.3.7 白云改为从 HIS 接口读取数据 String startDate = request.getStartTime(); String endDate = request.getEndTime(); Date start = DateUtil.parseDate(startDate, DateUtil.DADE_FROMAT_YMD); Date end = DateUtil.parseDate(endDate, DateUtil.DADE_FROMAT_YMD); if(Checker.isNone(start) || Checker.isNone(end)){ Pagination pagination = new Pagination(pageIndex, pageSize, total); PageVO res = new PageVO<>(pagination, list); return res; } // CheckUtil.ensureNotNull(start, "请选择时间"); // CheckUtil.ensureNotNull(end, "请选择时间"); long day = 0; day = DateUtil.getDaySub(request.getEndTime(), request.getStartTime()); if (day < -15) { throw new AppMessageException("请选择15天以内"); } GetOutpatientListRequest req3 = GetOutpatientListRequest.newBuilder() .setPatientId(hisPatientId) .setType(TYPE_PAID_WX) .setHospitalId(hospitalId) .setStartDate(startDate) .setEndDate(endDate) .build(); GetOutpatientListResponse res3 = taiheServiceBlockingStub.getOutpatientList(req3); if (res3.getCode() != ResultCode.SUCCEED_VALUE) { throw new RuntimeException(res3.getMsg()); } total = res3.getPaymentList().size(); for (PaymentItem payItem : res3.getPaymentList()) { PayHistoryResponseData data = new PayHistoryResponseData(); data.setStatus(status); data.setTitle(""); data.setDeptName(payItem.getDeptName()); data.setPrescribeDate(payItem.getPrescriptionDate()); data.setName(resp.getPatientName()); data.setAmount(String.format("%.2f", payItem.getTotalFee() / 100d)); data.setTradeNo(""); //Todo data.setOutTradeNo("");//Todo data.setIdNum("");//Todo data.setInvoiceNo(payItem.getInvoiceNo()); data.setHisPatientId(hisPatientId); data.setPayTime(payItem.getPrescriptionDate()); data.setTotal(Checker.getIntegerValue(payItem.getTotalFee())); data.setDoctorName(Checker.getStringValue(payItem.getDoctorName())); data.setDoctorCode(Checker.getStringValue(payItem.getDoctorCode())); data.setHisClinicCode(Checker.getStringValue(payItem.getClinicCode())); data.setAge(Checker.getIntegerValue(pAge)); data.setType(0); list.add(data); } break; } break; } Pagination pagination = new Pagination(pageIndex, pageSize, total); PageVO res = new PageVO<>(pagination, list); return res; } @Override public ComputeSelfPaidOrderResponseData computeSelfPaidOrder(ComputeSelfPaidOrderRequest request) { return null; } @Override public ComputeMedicarePayOrderResponseData computeMedicarePayOrder(ComputeMedicarePayOrderRequest request) { return null; } @Override public TradeNoForOrderResponseData tradeNoForOrder(TradeNoForOrderRequest request) throws Exception { TradeNoForOrderResponseData data = new TradeNoForOrderResponseData(); int userId = ContextHelper.getCurrentUserIdWrapped(); int hospitalId = BizUtil.getCurrentHospitalId(); int terminal = ContextHelper.getCurrentTerminalWrapped(); String invoiceNo = prePayConfirm(request.getHisPatientId(), request.getHisClinicCode(), request.getHisOrderNo(), hospitalId, request.getTotal()); Date pDate = DateUtil.parseDate(request.getPrescribeDate(), "yyyy-MM-dd HH:mm:ss"); int sex = 1; if (request.getSex().equals("女")) { sex = 2; } //该版本只有自费,没有医保 CreateOutpatientOrderRequest req = CreateOutpatientOrderRequest.newBuilder() .setDeptCode("") .setDeptName(request.getDeptName()) .setDoctorCode(request.getDoctorCode()) .setDoctorName(request.getDoctorName()) .setTotal(request.getTotal()) .setReimbursement(0) .setIndividual(request.getTotal()) .setHisPatientId(request.getHisPatientId()) .setHisClinicCode(request.getHisClinicCode()) .setHisOrderNo(request.getHisOrderNo()) .setPayName(request.getName()) .setPrescriptionDate(Checker.isNone(pDate)? 0L : pDate.getTime()) .setPatientName(request.getName()) .setPatientAge(request.getAge()) .setPatientSex(sex) .setOrderInsType("自费") .setInvoiceNo(invoiceNo) .setPayInsType(1) .setHospitalId(hospitalId) .setTerminal(terminal) .build(); Result result = orderServiceBlockingStub.createOutpatientOrder(req); if (result.getCode() != ResultCode.SUCCEED) { throw new AppMessageException(result.getInfo()); } String orderNo = result.getValue(); int orderId = getOrderIdByOrderNo(orderNo); //判断是否已线下缴费 com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest requ = com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest.newBuilder() .setOrderId(orderId).build(); com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailResponse res = taiheOutpatientServiceBlockingStub.getOutpatientDetail(requ); if (res.getCode() != ResultCode.SUCCEED_VALUE) { throw new AppMessageException(res.getMsg()); } com.ywt.gapi.taihe.outpaitent.OutpatientOrder order = res.getOrder(); if (order.getPaymentStatus() == PaymentStatusEnum.Success.getValue()) { throw new AppMessageException("该订单已缴费"); } CreateAlipayOrderResponse response = orderCenterServiceBlockingStub.createAlipayOrder(CreateAlipayOrderRequest.newBuilder() .setBody("门诊缴费") .setAlipayUid(request.getAlipayUid()) .setOrderId(orderId) .setOrderNo(orderNo) .setAmount(request.getTotal()) .setUserId(userId) .setTerminal(ContextHelper.getCurrentTerminalWrapped()) .build()); if (response.getCode() != ResultCode.SUCCEED_VALUE) { throw new AppMessageException(response.getInfo()); } data = new TradeNoForOrderResponseData(); data.setNeedPay(true);//设置是否需要支付宝自费支付 data.setOutTradeNo(orderNo); data.setTradeNo(response.getTradeNo()); return data; } /** * 根据身份证或出生日期获取年龄,避免当身份证为空的情况下获取年龄会返回奇怪的值 * * @param idNo 身份证 * @param birthday 出生年月日,格式 yyyy-MM-dd * @return */ private int getPatientAgeSafely(String idNo, String birthday) { if (!Checker.isNone(idNo)) { return IdCardUtil.getCurrentAge(idNo); } else { // logger.info("DHOutpatientController#getPatientAgeSafely(birthday = {}): 身份证为空", birthday); return IdCardUtil.getCurrentAgeByBirthday(birthday, IdCardUtil.DATE_PATTERN2); } } private String prePayConfirm(String patientId, String clinicCode, String hisOrdNum, int hospitalId, int orderSum) throws AppMessageException { PrePayConfirmRequest req = PrePayConfirmRequest.newBuilder() .setCardNo("") .setPatientId(patientId) .setStartDate("") .setEndDate("") .setClinicCode(clinicCode) .setHisOrdNum(hisOrdNum) .setOrderSum(orderSum) .setHospitalId(hospitalId) .setPayMode(Constants.HIS_PAY_MODE_ALIPAY) .build(); PrePayConfirmResponse response = taiheServiceBlockingStub.prePayConfirm(req); if (response.getCode() == ResultCode.SUCCEED_VALUE) { if (!Checker.isNone(response.getListList())) { // 预结算成功,自动取消之前生成的未支付订单,让前端可以重新创建订单 autoCancelPrevOrder(hisOrdNum); PrePayConfirm p = response.getListList().get(0); String invoiceNo = p.getInvoiceNo(); return invoiceNo; } throw new AppMessageException("预结算:HIS 返回列表数据为空"); } throw new AppMessageException(response.getMsg()); } private void autoCancelPrevOrder(String hisOrderNo) throws AppMessageException { GetOutpatientOrderByHisOrderNoRequest request = GetOutpatientOrderByHisOrderNoRequest.newBuilder() .setHisOrderNo(hisOrderNo) .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped())) .build(); GetOutpatientOrderByHisOrderNoResponse response = taiheOutpatientServiceBlockingStub.getOutpatientOrderByHisOrderNo(request); if (response.getCode() == ResultCode.SUCCEED_VALUE) { String orderNo = response.getOrderNo(); if (!StringHelper.isNullOrEmpty(orderNo)) { // logger.info("DHOutpatientController#autoCancelPrevOrder(): 预结算自动取消之前生成的订单 orderNo = {}", orderNo); MarkOpOrderDeletedResponse markOpOrderDeletedResponse = wxInsPayServiceBlockingStub.markOpOrderDeleted( MarkOpOrderDeletedRequest.newBuilder() .setOrderNo(orderNo) .build()); if (markOpOrderDeletedResponse.getCode() != ResultCode.SUCCEED_VALUE) { throw new AppMessageException(markOpOrderDeletedResponse.getMsg()); } } } else { throw new AppMessageException(response.getMsg()); } } //判断是否已线下缴费 public GetOutpatientListResponse getOutpatientList(String hisPatientId, int type, Integer hospitalId) { int hid = Checker.getIntegerValue(hospitalId) > 0 ? hospitalId : Constants.TAIHE_HOSPITAL_ID; GetOutpatientListRequest req = GetOutpatientListRequest.newBuilder() .setPatientId(hisPatientId) .setType(type) .setHospitalId(hid) .build(); return taiheServiceBlockingStub.getOutpatientList(req); } public int getOrderIdByOrderNo(String orderNo) { GetOrderInfoRequest request = GetOrderInfoRequest.newBuilder().setOrderNo(orderNo).build(); GetOrderInfeResponse getOrderInfeResponse = orderCenterServiceBlockingStub.getOrderInfo(request); return getOrderInfeResponse.getOrderId(); } }