|
|
@@ -1,5 +1,6 @@
|
|
|
package thyyxxk.wxservice_server.service;
|
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
@@ -18,10 +19,15 @@ import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
import thyyxxk.wxservice_server.config.exception.ExceptionEnum;
|
|
|
+import thyyxxk.wxservice_server.dao.InpatientDao;
|
|
|
import thyyxxk.wxservice_server.dao.WxApiDao;
|
|
|
+import thyyxxk.wxservice_server.pojo.HrgResponse;
|
|
|
import thyyxxk.wxservice_server.pojo.ResultVo;
|
|
|
-import thyyxxk.wxservice_server.pojo.wxapi.JsApiSHA1;
|
|
|
+import thyyxxk.wxservice_server.pojo.appointment.MzyReqrecPojo;
|
|
|
+import thyyxxk.wxservice_server.pojo.appointment.SaveAppointmentParam;
|
|
|
import thyyxxk.wxservice_server.pojo.appointment.WeChatPayParam;
|
|
|
+import thyyxxk.wxservice_server.pojo.inpatient.GetZyFeeParam;
|
|
|
+import thyyxxk.wxservice_server.pojo.wxapi.JsApiSHA1;
|
|
|
import thyyxxk.wxservice_server.pojo.wxapi.MzGuideBillParam;
|
|
|
import thyyxxk.wxservice_server.pojo.wxapi.PushMessageParam;
|
|
|
import thyyxxk.wxservice_server.pojo.wxapi.WxPayOrderPojo;
|
|
|
@@ -35,13 +41,15 @@ import java.util.concurrent.TimeUnit;
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
public class WxApiService {
|
|
|
+ private static final Vector<String> tradeNosBetweenQuery = new Vector<>();
|
|
|
private final WxApiDao dao;
|
|
|
+ private final InpatientDao yjjDao;
|
|
|
private final SpringRetryService retryService;
|
|
|
- private static final Vector<String> tradeNosBetweenQuery = new Vector<>();
|
|
|
|
|
|
@Autowired
|
|
|
- public WxApiService(WxApiDao dao, SpringRetryService retryService) {
|
|
|
+ public WxApiService(WxApiDao dao, InpatientDao yjjDao, SpringRetryService retryService) {
|
|
|
this.dao = dao;
|
|
|
+ this.yjjDao = yjjDao;
|
|
|
this.retryService = retryService;
|
|
|
}
|
|
|
|
|
|
@@ -57,17 +65,18 @@ public class WxApiService {
|
|
|
return ResultVoUtil.success(data);
|
|
|
}
|
|
|
|
|
|
- public ResultVo<WxPayOrderPojo> createPayOrder(WeChatPayParam param) {
|
|
|
+ @Async("asyncTask")
|
|
|
+ public CompletableFuture<ResultVo<WxPayOrderPojo>> createPayOrder(WeChatPayParam param) {
|
|
|
if (param.getOrderType() == 1) {
|
|
|
int count = dao.selectSameGhCount(param.getPatientId(), param.getMzyRequestId());
|
|
|
if (count > 0) {
|
|
|
- return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您已成功支付过一笔相同金额的订单,请勿重复支付。");
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您已成功支付过一笔相同金额的订单,请勿重复支付。"));
|
|
|
}
|
|
|
}
|
|
|
if (param.getOrderType() == 2) {
|
|
|
int count = dao.selectSameMzFeeCount(param.getHisOrdNum());
|
|
|
if (count > 0) {
|
|
|
- return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您已成功支付过一笔相同金额的订单,请勿重复支付。");
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您已成功支付过一笔相同金额的订单,请勿重复支付。"));
|
|
|
}
|
|
|
}
|
|
|
String appId = PropertiesUtil.getProperty("appId");
|
|
|
@@ -95,7 +104,7 @@ public class WxApiService {
|
|
|
"<device_info>WEB</device_info>" +
|
|
|
"<mch_id>" + merchantId + "</mch_id>" +
|
|
|
"<nonce_str>" + nonceStr + "</nonce_str>" +
|
|
|
- "<notify_url>" + notifyUrl +"</notify_url>" +
|
|
|
+ "<notify_url>" + notifyUrl + "</notify_url>" +
|
|
|
"<openid>" + param.getOpenId() + "</openid>" +
|
|
|
"<out_trade_no>" + tradeNo + "</out_trade_no>" +
|
|
|
"<total_fee>" + totalFee + "</total_fee>" +
|
|
|
@@ -143,15 +152,15 @@ public class WxApiService {
|
|
|
order.setAdmissTimes(param.getAdmissTimes());
|
|
|
dao.insertNewOrder(order);
|
|
|
log.info("统一下单成功:{}", order);
|
|
|
- return ResultVoUtil.success(order);
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.success(order));
|
|
|
} else {
|
|
|
final String message = root.element("return_msg").getStringValue();
|
|
|
log.info("微信统一下单失败:{}", message);
|
|
|
- return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message);
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message));
|
|
|
}
|
|
|
} catch (DocumentException e) {
|
|
|
e.printStackTrace();
|
|
|
- return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, e.getMessage());
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, e.getMessage()));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -172,11 +181,161 @@ public class WxApiService {
|
|
|
String successTime = obj.getString("success_time")
|
|
|
.split("\\+")[0].replace("T", " ");
|
|
|
dao.updatePayStatusAndPayTime(tradeNo, 1, successTime);
|
|
|
- } else {
|
|
|
- updatePayStatusByTradeState(tradeState, tradeNo);
|
|
|
+ WxPayOrderPojo order = dao.selectOrderByTradeNo(tradeNo);
|
|
|
+ ResultVo<String> saveRet;
|
|
|
+ switch (order.getOrderType()) {
|
|
|
+ case 1:
|
|
|
+ saveRet = saveAppointment(order);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ saveRet = saveMzChargeInfo(order);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ saveRet = saveZyYjjInfo(order);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ log.info("未识别到的订单类型:{},订单号:{}", order.getOrderType(), tradeNo);
|
|
|
+ saveRet = ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "未识别到的订单类型,请联系服务中心。");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ tradeNosBetweenQuery.remove(tradeNo);
|
|
|
+ return CompletableFuture.completedFuture(saveRet);
|
|
|
}
|
|
|
+ updatePayStatusByTradeState(tradeState, tradeNo);
|
|
|
tradeNosBetweenQuery.remove(tradeNo);
|
|
|
- return CompletableFuture.completedFuture(ResultVoUtil.success(tradeState));
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "支付失败"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private ResultVo<String> saveAppointment(WxPayOrderPojo order) {
|
|
|
+ Integer hasSaved = queryRegistrationState(order);
|
|
|
+ if (hasSaved == 1) {
|
|
|
+ log.info("订单号:{} 的挂号信息已保存,无需再次保存。", order.getTradeNo());
|
|
|
+ return ResultVoUtil.success("保存挂号信息成功。");
|
|
|
+ }
|
|
|
+ SaveAppointmentParam param = new SaveAppointmentParam();
|
|
|
+ param.setMzyRequestId(order.getMzyRequestId());
|
|
|
+ param.setTotalFee(order.getTotalFee().doubleValue());
|
|
|
+ MzyReqrecPojo mzyReqrec = new MzyReqrecPojo();
|
|
|
+ mzyReqrec.setPatientId(order.getPatientId());
|
|
|
+ mzyReqrec.setPaymode("WX");
|
|
|
+ mzyReqrec.setPsordnum(order.getTradeNo());
|
|
|
+ mzyReqrec.setAgtordnum(order.getSerialNo());
|
|
|
+ param.setMzyReqrec(mzyReqrec);
|
|
|
+ log.info("保存挂号信息: {}", param);
|
|
|
+ RestTemplate template = new RestTemplate();
|
|
|
+ HrgResponse data = template.postForObject(ThmzUrls.PAY_REGISTRATION_FORM_HAI_CI, param, HrgResponse.class);
|
|
|
+ log.info("保存挂号信息结果: {}", data);
|
|
|
+ tradeNosBetweenQuery.remove(order.getTradeNo());
|
|
|
+ if (null != data && data.getResultCode() == 0) {
|
|
|
+ return ResultVoUtil.success("保存挂号信息成功。");
|
|
|
+ }
|
|
|
+ log.info("保存挂号信息失败,将自动退款。");
|
|
|
+ ResultVo<String> refund = autoRefund(order.getTradeNo(), "保存挂号信息失败,自动退款。");
|
|
|
+ if (null != refund && refund.getCode() == 200) {
|
|
|
+ return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "保存挂号信息失败,已为您自动退款,请留意到账信息。");
|
|
|
+ }
|
|
|
+ dao.updatePayStatusOnly(order.getTradeNo(), 7);
|
|
|
+ return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "保存挂号信息失败,自动退款失败,请联系服务中心进行退款。");
|
|
|
+ }
|
|
|
+
|
|
|
+ private ResultVo<String> saveMzChargeInfo(WxPayOrderPojo order) {
|
|
|
+ Integer hasSaved = queryMzPayStatus(order);
|
|
|
+ if (hasSaved == 1) {
|
|
|
+ log.info("订单号:{} 的门诊缴费信息已保存,无需再次保存。", order.getTradeNo());
|
|
|
+ return ResultVoUtil.success("保存门诊缴费信息成功。");
|
|
|
+ }
|
|
|
+ String payTime = DateUtil.formatDatetime(new Date(), "yyyy-MM-dd HH:mm:ss");
|
|
|
+ JSONObject hrgParam = new JSONObject();
|
|
|
+ hrgParam.put("patCardType", 1);
|
|
|
+ hrgParam.put("patCardNo", order.getPatientId());
|
|
|
+ hrgParam.put("hisOrdNum", order.getHisOrdNum());
|
|
|
+ hrgParam.put("psOrdNum", order.getTradeNo());
|
|
|
+ hrgParam.put("payMode", "WX");
|
|
|
+ hrgParam.put("payAmt", DecimalTool.moneyYuanToFen(order.getTotalFee()));
|
|
|
+ hrgParam.put("agtOrdNum", order.getSerialNo());
|
|
|
+ hrgParam.put("payTime", payTime);
|
|
|
+ log.info("保存门诊缴费信息:{}", hrgParam);
|
|
|
+ RestTemplate template = new RestTemplate();
|
|
|
+ HrgResponse response = template.postForObject(ThmzUrls.PAY_CHARGE_DETAIL_FORM_HAI_CI,
|
|
|
+ hrgParam, HrgResponse.class);
|
|
|
+ log.info("保存门诊缴费信息结果:{}", response);
|
|
|
+ if (null != response && response.getResultCode() == 0) {
|
|
|
+ return ResultVoUtil.success("保存门诊缴费信息成功。");
|
|
|
+ }
|
|
|
+ log.info("保存门诊缴费信息失败,将自动退款。");
|
|
|
+ ResultVo<String> refund = autoRefund(order.getTradeNo(), "保存门诊缴费信息失败,自动退款。");
|
|
|
+ if (null != refund && refund.getCode() == 200) {
|
|
|
+ return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "保存门诊缴费信息失败,已为您自动退款,请留意到账信息。");
|
|
|
+ }
|
|
|
+ dao.updatePayStatusOnly(order.getTradeNo(), 7);
|
|
|
+ return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "保存门诊缴费信息失败,自动退款失败,请联系服务中心进行退款。");
|
|
|
+ }
|
|
|
+
|
|
|
+ public ResultVo<String> saveZyYjjInfo(WxPayOrderPojo param) {
|
|
|
+ int savedCount = yjjDao.selectSavedCount(param.getTradeNo(), param.getSerialNo());
|
|
|
+ if (savedCount > 0) {
|
|
|
+ log.info("订单号:{} 的住院预交金信息已保存,无需再次保存。", param.getTradeNo());
|
|
|
+ return ResultVoUtil.success("保存住院预交金信息成功。");
|
|
|
+ }
|
|
|
+ String datetime = DateUtil.formatDatetime(new Date(), "yyyy-MM-dd HH:mm:ss");
|
|
|
+ yjjDao.payZyYjjSuccessful(param.getInpatientNo(), param.getAdmissTimes(), param.getTotalFee(),
|
|
|
+ datetime, param.getTradeNo(), param.getSerialNo(), "");
|
|
|
+ GetZyFeeParam getZyFeeParam = new GetZyFeeParam();
|
|
|
+ String date = DateUtil.formatDatetime(new Date(), "yyyy-MM-dd");
|
|
|
+ getZyFeeParam.setInpatientNo(param.getInpatientNo());
|
|
|
+ getZyFeeParam.setAdmissTimes(param.getAdmissTimes());
|
|
|
+ getZyFeeParam.setStart(date);
|
|
|
+ getZyFeeParam.setEnd(date);
|
|
|
+ yjjDao.getZyFees(getZyFeeParam);
|
|
|
+ log.info("缴纳住院预交金成功:{}", JSON.toJSONStringWithDateFormat(param, "yyyy-MM-dd HH:mm:ss"));
|
|
|
+ String msgContent = "{\"touser\":\"\",\"data\":" +
|
|
|
+ "{\"keyword3\":{\"color\":\"#173177\",\"value\":\"" + param.getTotalFee() + "\"}," +
|
|
|
+ "\"keyword1\":{\"color\":\"#173177\",\"value\":\"" + param.getPatientName() + "\"}," +
|
|
|
+ "\"keyword2\":{\"color\":\"#173177\",\"value\":\"" + param.getInpatientNo() + "\"}," +
|
|
|
+ "\"remark\":{\"color\":\"#FF0000\",\"value\":\"感谢您的使用,祝您健康!\"}," +
|
|
|
+ "\"first\":{\"color\":\"#FF0000\",\"value\":\"您好,您已成功支付住院预交金,详情如下:\"}}," +
|
|
|
+ "\"template_id\":\"6qWVpQopIe4a_fYYnZg_yaInPoMFduDDJ4hotv3Mtxo\"," +
|
|
|
+ "\"url\":\"\"}";
|
|
|
+ PushMessageParam pojo = new PushMessageParam();
|
|
|
+ pojo.setCardNo(yjjDao.selectCardNoByPatientId(param.getPatientId()));
|
|
|
+ pojo.setMsgContext(JSONObject.parseObject(msgContent));
|
|
|
+ pushMessage(pojo);
|
|
|
+ return ResultVoUtil.success("保存住院预交金信息成功。");
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer queryRegistrationState(WxPayOrderPojo order) {
|
|
|
+ RestTemplate template = new RestTemplate();
|
|
|
+ JSONObject obj = new JSONObject();
|
|
|
+ obj.put("psOrdNum", order.getTradeNo());
|
|
|
+ obj.put("payMode", "WX");
|
|
|
+ obj.put("payAmt", order.getTotalFee().toPlainString());
|
|
|
+ obj.put("agtOrdNum", order.getSerialNo());
|
|
|
+ obj.put("payTime", DateUtil.formatDatetime(order.getPayDatetime(), "yyyy-MM-dd HH:mm:ss"));
|
|
|
+ HrgResponse response = template.postForObject(ThmzUrls.GET_PAY_STATUS_FOR_REGISTRATION, obj, HrgResponse.class);
|
|
|
+ log.info("门诊挂号订单支付状态查询结果:{}", response);
|
|
|
+ int result = 0;
|
|
|
+ if (null != response && response.getResultCode() == 0) {
|
|
|
+ result = response.getPayStatus();
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer queryMzPayStatus(WxPayOrderPojo order) {
|
|
|
+ tradeNosBetweenQuery.add(order.getTradeNo());
|
|
|
+ RestTemplate template = new RestTemplate();
|
|
|
+ JSONObject obj = new JSONObject();
|
|
|
+ obj.put("hisOrdNum", order.getHisOrdNum());
|
|
|
+ obj.put("psOrdNum", order.getTradeNo());
|
|
|
+ obj.put("payMode", "WX");
|
|
|
+ obj.put("payAmt", order.getTotalFee().toPlainString());
|
|
|
+ obj.put("agtOrdNum", order.getSerialNo());
|
|
|
+ obj.put("payTime", DateUtil.formatDatetime(order.getPayDatetime(), "yyyy-MM-dd HH:mm:ss"));
|
|
|
+ HrgResponse response = template.postForObject(ThmzUrls.GET_PAY_STATUS, obj, HrgResponse.class);
|
|
|
+ log.info("门诊缴费订单支付状态查询结果:{}", response);
|
|
|
+ if (null == response || response.getResultCode() == -1) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return response.getPayStatus();
|
|
|
}
|
|
|
|
|
|
public void updatePayStatusByTradeState(String tradeState, String tradeNo) {
|
|
|
@@ -224,7 +383,8 @@ public class WxApiService {
|
|
|
return template.postForObject(url, param, ResultVo.class);
|
|
|
}
|
|
|
|
|
|
- public ResultVo<String> createOrderForMzGuideBill(MzGuideBillParam param) throws Exception {
|
|
|
+ @Async("asyncTask")
|
|
|
+ public CompletableFuture<ResultVo<String>> createOrderForMzGuideBill(MzGuideBillParam param) throws Exception {
|
|
|
String outTradeNo = SnowFlakeId.instance().nextId();
|
|
|
JSONObject body = new JSONObject();
|
|
|
body.put("appid", PropertiesUtil.getProperty("appId"));
|
|
|
@@ -271,20 +431,21 @@ public class WxApiService {
|
|
|
order.setHisOrdNum(param.getHisOrdNum());
|
|
|
dao.insertNewOrder(order);
|
|
|
JSONObject retObj = JSONObject.parseObject(ret);
|
|
|
- return ResultVoUtil.success(retObj.getString("code_url"));
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.success(retObj.getString("code_url")));
|
|
|
}
|
|
|
log.error("请求门诊指引单二维码失败:{}", ret);
|
|
|
- return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请求微信支付二维码失败,请联系管理员。");
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请求微信支付二维码失败,请联系管理员。"));
|
|
|
}
|
|
|
|
|
|
- public ResultVo<List<Map<String, Object>>> pushMessage(PushMessageParam param) {
|
|
|
+ @Async("asyncTask")
|
|
|
+ public CompletableFuture<ResultVo<List<Map<String, Object>>>> pushMessage(PushMessageParam param) {
|
|
|
JSONObject content = param.getMsgContext();
|
|
|
String wxUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" +
|
|
|
PropertiesUtil.getProperty("access_token");
|
|
|
List<String> openIds = dao.selectOpenIdByIcCardNo(param.getCardNo());
|
|
|
if (null == openIds || openIds.isEmpty()) {
|
|
|
- return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "未找到卡号【" +
|
|
|
- param.getCardNo() + "】的openId。");
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "未找到卡号【" +
|
|
|
+ param.getCardNo() + "】的openId。"));
|
|
|
}
|
|
|
List<Map<String, Object>> resMapArr = new ArrayList<>();
|
|
|
RestTemplate template = new RestTemplate();
|
|
|
@@ -301,14 +462,14 @@ public class WxApiService {
|
|
|
map.put("cardNo", param.getCardNo());
|
|
|
resMapArr.add(map);
|
|
|
}
|
|
|
- return ResultVoUtil.success(resMapArr);
|
|
|
+ return CompletableFuture.completedFuture(ResultVoUtil.success(resMapArr));
|
|
|
}
|
|
|
|
|
|
private RestTemplate getRestTemplate() {
|
|
|
RestTemplate restTemplate = new RestTemplate();
|
|
|
List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
|
|
|
for (HttpMessageConverter<?> httpMessageConverter : list) {
|
|
|
- if(httpMessageConverter instanceof StringHttpMessageConverter) {
|
|
|
+ if (httpMessageConverter instanceof StringHttpMessageConverter) {
|
|
|
((StringHttpMessageConverter) httpMessageConverter).setDefaultCharset(StandardCharsets.UTF_8);
|
|
|
break;
|
|
|
}
|