|
|
@@ -1,97 +1,92 @@
|
|
|
package org.dromara.server.hik.event.handler;
|
|
|
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.dubbo.config.annotation.DubboReference;
|
|
|
+import org.dromara.common.core.domain.R;
|
|
|
+import org.dromara.common.core.domain.model.ErrorInfo;
|
|
|
+import org.dromara.common.core.domain.model.ErrorResult;
|
|
|
+import org.dromara.common.core.enums.CreditTypeEnum;
|
|
|
import org.dromara.common.core.utils.StringUtils;
|
|
|
+import org.dromara.consume.api.RemoteConsumeService;
|
|
|
+import org.dromara.consume.api.domain.bo.RemoteConsumeBo;
|
|
|
+import org.dromara.consume.api.domain.bo.RemoteResultDto;
|
|
|
+import org.dromara.server.hik.domain.vo.XfTermVo;
|
|
|
+import org.dromara.server.hik.enums.ConsumeModeEnum;
|
|
|
import org.dromara.server.hik.event.HikEventHandler;
|
|
|
import org.dromara.server.hik.event.domain.ConsumptionEventConfirmBo;
|
|
|
import org.dromara.server.hik.event.domain.ConsumptionEventDetail;
|
|
|
import org.dromara.server.hik.event.domain.ConsumptionEventReceive;
|
|
|
import org.dromara.server.hik.event.domain.FileContent;
|
|
|
+import org.dromara.server.hik.service.IXfTermService;
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
+import org.springframework.http.ResponseEntity;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
+import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.Map;
|
|
|
|
|
|
@Slf4j
|
|
|
@Component
|
|
|
+@RequiredArgsConstructor
|
|
|
public class ConsumptionEventHandler implements HikEventHandler {
|
|
|
|
|
|
public static final String TRANSACTION_PREPROCESSING_REQUEST = "transactionPreprocessingRequest";
|
|
|
public static final String TRANSACTION_CONFIRMING_REQUEST = "transactionConfirmingRequest";
|
|
|
|
|
|
+ private final IXfTermService termService;
|
|
|
+
|
|
|
+ @DubboReference
|
|
|
+ private final RemoteConsumeService remoteConsumeService;
|
|
|
+
|
|
|
@Override
|
|
|
public Map<String, Object> handleEvent(JSONObject jsonObject, FileContent fileContent) {
|
|
|
ConsumptionEventReceive receive = jsonObject.toJavaObject(ConsumptionEventReceive.class);
|
|
|
ConsumptionEventDetail consumptionEvent = receive.getConsumptionEvent();
|
|
|
log.info("消费机事件,类型:{}", consumptionEvent.getMinor());
|
|
|
if (TRANSACTION_PREPROCESSING_REQUEST.equals(consumptionEvent.getMinor())) {
|
|
|
- /**
|
|
|
+ XfTermVo termVo = termService.queryByMac(receive.getMacAddress());
|
|
|
+ if (termVo == null) {
|
|
|
+ log.error("消费机交易记录事件,设备信息为空,mac:{}, 不存在系统中", receive.getMacAddress());
|
|
|
+ // 直接应答失败
|
|
|
+ return answerEvent(consumptionEvent, false,null, "设备未注册", "");
|
|
|
+ }
|
|
|
+ /*
|
|
|
* 消费机 交易预处理请求事件上报
|
|
|
* eventType: ConsumptionEvent
|
|
|
* minor:transactionPreprocessingRequest
|
|
|
*/
|
|
|
// 业务逻辑处理的结果
|
|
|
boolean bussiRs = true;
|
|
|
- // todo 处理交易预处理请求事件上报 根据业务数据校验 能不能消费 权限、账号、金额、设备、业务数据
|
|
|
-
|
|
|
+ // 处理交易预处理请求事件上报 根据业务数据校验 能不能消费 权限、账号、金额、设备、业务数据
|
|
|
+ // 调用现有原始消费请求接口
|
|
|
+ RemoteConsumeBo remoteBo = setParamBo(receive, consumptionEvent);
|
|
|
+ remoteBo.setTermNo(termVo.getTermNo());
|
|
|
+ RemoteResultDto result = remoteConsumeService.dealHikRequestConsume(remoteBo);
|
|
|
+ R<ErrorInfo> errorInfo = result.getErrorInfo();
|
|
|
+ RemoteConsumeBo updatedRemoteBo = result.getUpdatedRemoteBo();
|
|
|
+ String reason = "";
|
|
|
+ BigDecimal balance = updatedRemoteBo.getBalance();
|
|
|
+ String deptName =updatedRemoteBo.getDeptName();
|
|
|
+ if (R.isError(errorInfo)) {
|
|
|
+ // 应答失败
|
|
|
+ bussiRs = false;
|
|
|
+ reason = errorInfo.getMsg();
|
|
|
+ ErrorInfo data = errorInfo.getData();
|
|
|
+ if(data != null){
|
|
|
+ reason = data.getMessage();
|
|
|
+ }
|
|
|
|
|
|
- // 应答
|
|
|
- ConsumptionEventConfirmBo confirmBo = new ConsumptionEventConfirmBo();
|
|
|
- confirmBo.setSerialNo(consumptionEvent.getSerialNo());
|
|
|
- confirmBo.setResult(bussiRs ?"success":"failed");
|
|
|
-// confirmBo.setReason("platformException");
|
|
|
- confirmBo.setMode(consumptionEvent.getMode());
|
|
|
- log.info("消费机交易预处理请求事件,moshi:{}", consumptionEvent.getMode());
|
|
|
- confirmBo.setName(consumptionEvent.getName());
|
|
|
- confirmBo.setEmployeeNoString(consumptionEvent.getEmployeeNoString());
|
|
|
- if(StringUtils.isNotBlank(consumptionEvent.getCardNo())){
|
|
|
- confirmBo.setCardNo(consumptionEvent.getCardNo());
|
|
|
- }else{
|
|
|
- log.info("消费机交易预处理请求事件,方式:{}", "人脸或者二维码,不带卡号");
|
|
|
- }
|
|
|
- confirmBo.setActualPayment(consumptionEvent.getTotalPayment());
|
|
|
- confirmBo.setBalanceBeforeDeduct("10000"); // 未扣款前的余额,要根据余额加上扣款金额,单位为分 ,金额模式必填
|
|
|
-// confirmBo.setTimes(0); // 次数模式必填,有这个字段时可以不填
|
|
|
- /*
|
|
|
- confirmBo.setQRCodeType("Alipay");
|
|
|
- confirmBo.setPaymentOrderNo("1234567890");
|
|
|
- confirmBo.setSecondaryConfirmType("none");*/
|
|
|
-// confirmBo.setRemainingTimes(0); // 次数模式必填,有这个字段时必填
|
|
|
-
|
|
|
- /* String broadcastVoice = "成功消费了"
|
|
|
- + new BigDecimal(consumptionEvent.getTotalPayment()).divide(new BigDecimal("100.0"), 2, RoundingMode.HALF_UP)
|
|
|
- + "元";*/
|
|
|
-
|
|
|
- String broadcastVoice = "count".equals(consumptionEvent.getMode()) ? "刷卡成功":"消费成功";
|
|
|
-
|
|
|
-
|
|
|
- if(!bussiRs){
|
|
|
- broadcastVoice = "count".equals(consumptionEvent.getMode()) ? "刷卡失败":"消费失败";
|
|
|
- // 提示刷卡失败的原因
|
|
|
- broadcastVoice += "就是不让你刷卡";
|
|
|
- confirmBo.setReason("platformException");
|
|
|
}
|
|
|
|
|
|
- confirmBo.setCustomTTSBroadcastVoice(broadcastVoice);
|
|
|
-
|
|
|
- /**
|
|
|
- * 这可以显示刷卡人的信息,比如姓名,工号,卡号,金额,消费时间等
|
|
|
- */
|
|
|
- ConsumptionEventConfirmBo.ContentInfo contentInfo = new ConsumptionEventConfirmBo.ContentInfo();
|
|
|
- contentInfo.setTitle("****这是一个标题*****");
|
|
|
- contentInfo.setContent("*****这是一个偶然的内容********");
|
|
|
- confirmBo.setContentInfo(contentInfo);
|
|
|
-
|
|
|
- // confirmBo 转Map,如果字段为空则丢弃
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- HashMap<String, Object> rs = new HashMap<>(1);
|
|
|
- rs.put("ConsumptionEventConfirm", confirmBo.toMap());
|
|
|
- return rs;
|
|
|
+ // 应答
|
|
|
+ return answerEvent(consumptionEvent, bussiRs, balance, reason,deptName);
|
|
|
}else if(TRANSACTION_CONFIRMING_REQUEST.equals(consumptionEvent.getMinor())){
|
|
|
HashMap<String, Object> rs = new HashMap<>(1);
|
|
|
rs.put("result", "success");
|
|
|
@@ -106,15 +101,107 @@ public class ConsumptionEventHandler implements HikEventHandler {
|
|
|
return rs;
|
|
|
}
|
|
|
|
|
|
- // todo 进行扣费逻辑处理
|
|
|
-
|
|
|
+ // 进行扣费逻辑处理 调用现有的消费入库的接口
|
|
|
+ RemoteConsumeBo remoteBo = setParamBo(receive, consumptionEvent);;
|
|
|
+ remoteBo.setRecordStatus(364L);
|
|
|
+ remoteBo.setRecordId(0L);
|
|
|
+ RemoteResultDto result = remoteConsumeService.dealHikUploadRecord(remoteBo);
|
|
|
+// log.info("消费机消费请求确认事件,结果:{}", JSONObject.toJSONString(result.getUpdatedRemoteBo()));
|
|
|
+ R<ErrorInfo> errorInfo = result.getErrorInfo();
|
|
|
+ if (R.isError(errorInfo)) {
|
|
|
+ // 应答失败
|
|
|
+ rs.put("result", "failed");
|
|
|
+ }
|
|
|
return rs;
|
|
|
-
|
|
|
-
|
|
|
}else{
|
|
|
log.warn("消费机事件,未知类型:{}", consumptionEvent.getMinor());
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ private RemoteConsumeBo setParamBo(ConsumptionEventReceive receive, ConsumptionEventDetail consumptionEvent) {
|
|
|
+ RemoteConsumeBo remoteBo = new RemoteConsumeBo();
|
|
|
+ remoteBo.setUserNo(Long.valueOf(consumptionEvent.getEmployeeNoString()));
|
|
|
+ String cardNo = consumptionEvent.getCardNo();
|
|
|
+ if(StringUtils.isNotBlank(cardNo)){
|
|
|
+ remoteBo.setFactoryId(Long.valueOf(cardNo));
|
|
|
+ } else {
|
|
|
+ remoteBo.setFactoryId(0L);
|
|
|
+ }
|
|
|
+ Date dateTime = receive.getDateTime();
|
|
|
+ remoteBo.setConsumeDate(dateTime);
|
|
|
+ remoteBo.setTermRecordId(Long.valueOf(consumptionEvent.getSerialNo()));
|
|
|
+ if(StringUtils.isNotBlank(consumptionEvent.getTotalPayment())){
|
|
|
+ BigDecimal money = new BigDecimal(consumptionEvent.getTotalPayment()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
|
|
+ remoteBo.setConsumeMoney(money);
|
|
|
+ }else{
|
|
|
+ remoteBo.setConsumeMoney(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+
|
|
|
+ remoteBo.setTermMac(receive.getMacAddress());
|
|
|
+ remoteBo.setCardNo(0L);
|
|
|
+ remoteBo.setStatusFlag(4);
|
|
|
+ remoteBo.setCreditType(CreditTypeEnum.TERM_CONSUME.code());
|
|
|
+ return remoteBo;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public Map<String, Object> answerEvent(ConsumptionEventDetail consumptionEvent, boolean answerResult, BigDecimal balance, String reason,String deptName)
|
|
|
+ {
|
|
|
+ ConsumptionEventConfirmBo confirmBo = new ConsumptionEventConfirmBo();
|
|
|
+ confirmBo.setSerialNo(consumptionEvent.getSerialNo());
|
|
|
+ confirmBo.setResult(answerResult ?"success":"failed");
|
|
|
+ confirmBo.setMode(consumptionEvent.getMode());
|
|
|
+ log.info("消费机交易预处理请求事件,消费模式:{}", consumptionEvent.getMode());
|
|
|
+ confirmBo.setName(consumptionEvent.getName());
|
|
|
+ confirmBo.setEmployeeNoString(consumptionEvent.getEmployeeNoString());
|
|
|
+ if(StringUtils.isNotBlank(consumptionEvent.getCardNo())){
|
|
|
+ confirmBo.setCardNo(consumptionEvent.getCardNo());
|
|
|
+ }else{
|
|
|
+ log.info("消费机交易预处理请求事件,方式:{}", "人脸或者二维码,不带卡号");
|
|
|
+ }
|
|
|
+ boolean isCountMode = ConsumeModeEnum.count.getCode().equals(consumptionEvent.getMode());
|
|
|
+ if(isCountMode){
|
|
|
+ confirmBo.setTimes(0);
|
|
|
+ if(answerResult){
|
|
|
+ confirmBo.setTimes(1);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(answerResult){
|
|
|
+ confirmBo.setActualPayment(consumptionEvent.getTotalPayment());
|
|
|
+ BigDecimal balanceBeforeDeduct = balance.multiply(new BigDecimal("100")).add(new BigDecimal(consumptionEvent.getTotalPayment()));
|
|
|
+ confirmBo.setBalanceBeforeDeduct(balanceBeforeDeduct.toString().split("\\.")[0]); // 未扣款前的余额,要根据余额加上扣款金额,单位为分 ,金额模式必填
|
|
|
+ }else{
|
|
|
+ confirmBo.setActualPayment("0");
|
|
|
+ confirmBo.setBalanceBeforeDeduct("0");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String broadcastVoice = isCountMode ? "刷卡成功":"消费成功";
|
|
|
+ if(!answerResult){
|
|
|
+ broadcastVoice = isCountMode ? "刷卡失败":"消费失败";
|
|
|
+ // 提示刷卡失败的原因
|
|
|
+ broadcastVoice += reason;
|
|
|
+ confirmBo.setReason("platformException");
|
|
|
+ }
|
|
|
+ confirmBo.setCustomTTSBroadcastVoice(broadcastVoice);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 这可以显示刷卡人的信息,比如姓名,部门等
|
|
|
+ */
|
|
|
+ ConsumptionEventConfirmBo.ContentInfo contentInfo = new ConsumptionEventConfirmBo.ContentInfo();
|
|
|
+ contentInfo.setTitle(consumptionEvent.getName());
|
|
|
+ contentInfo.setContent(deptName);
|
|
|
+ if(!answerResult){
|
|
|
+ contentInfo.setTitle(consumptionEvent.getName()+ " "+deptName);
|
|
|
+ contentInfo.setContent("消费失败原因:"+reason);
|
|
|
+ }
|
|
|
+ confirmBo.setContentInfo(contentInfo);
|
|
|
+
|
|
|
+ // confirmBo 转Map,如果字段为空则丢弃
|
|
|
+ HashMap<String, Object> rs = new HashMap<>(1);
|
|
|
+ rs.put("ConsumptionEventConfirm", confirmBo.toMap());
|
|
|
+ return rs;
|
|
|
+ }
|
|
|
}
|