diff --git a/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java b/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java index 62759cdeb..5cb9ba100 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java +++ b/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java @@ -51,11 +51,15 @@ public class CacheConstants { public static final String PILE_PROGRAM_VERSION = "pile_program_version_"; - // 查询订单回调 + // 查询订单微信支付回调 public static final String QUERY_ORDER_WECHAT_CALLBACK = "query_order_wechat_callback:"; + // 查询订单汇付支付回调 public static final String QUERY_ORDER_ADAPAY_CALLBACK = "query_order_adapay_callback:"; + // 通过paymentId 查询汇付支付回调 + public static final String QUERY_ADAPAY_CALLBACK_RECORD_BY_PAYMENT_ID = "query_adapay_callback_record_by_payment_id:"; + // 汇付支付参数 public static final String ADAPAY_ORDER_PARAM = "adapay_order_param:"; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayCallbackRecordServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayCallbackRecordServiceImpl.java index 3a6d8dcb0..7740384e6 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayCallbackRecordServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayCallbackRecordServiceImpl.java @@ -25,8 +25,9 @@ public class AdapayCallbackRecordServiceImpl implements AdapayCallbackRecordServ adapayCallbackRecordMapper.insert(callbackRecord); } - /** + /** * 根据订单号查询支付回调信息 + * * @param orderCode * @return */ @@ -36,7 +37,7 @@ public class AdapayCallbackRecordServiceImpl implements AdapayCallbackRecordServ return null; } String redisKey = CacheConstants.QUERY_ORDER_ADAPAY_CALLBACK + orderCode; - AdapayCallbackRecord record = redisCache.getCacheObject(redisKey); + AdapayCallbackRecord record = redisCache.getCacheObject(redisKey); if (record != null) { return record; } @@ -55,6 +56,23 @@ public class AdapayCallbackRecordServiceImpl implements AdapayCallbackRecordServ @Override public AdapayCallbackRecord selectByPaymentId(String paymentId) { - return adapayCallbackRecordMapper.selectByPaymentId(paymentId); + if (StringUtils.isBlank(paymentId)) { + return null; + } + // 加缓存缓存一周 由于回调结果不会变动,所以不用写清缓存的逻辑了 + String redisKey = CacheConstants.QUERY_ADAPAY_CALLBACK_RECORD_BY_PAYMENT_ID + paymentId; + AdapayCallbackRecord record = redisCache.getCacheObject(redisKey); + if (record != null) { + return record; + } + try { + record = adapayCallbackRecordMapper.selectByPaymentId(paymentId); + if (record != null) { + redisCache.setCacheObject(redisKey, record, CacheConstants.cache_expire_time_1d); + } + } catch (Exception e) { + log.error("查询汇付支付回调记录失败", e); + } + return record; } } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index b673b4443..8c7d148df 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -686,17 +686,62 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { @Override public void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo) { logger.info("结算订单start data:{}, orderBasicInfo:{}", data.toString(), orderBasicInfo.toString()); - String orderCode = orderBasicInfo.getOrderCode(); - String memberId = orderBasicInfo.getMemberId(); - // 判断订单状态 if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { - logger.info("结算订单:{}, 是订单完成状态", orderCode); + logger.info("结算订单:{}, 是订单完成状态", orderBasicInfo.getOrderCode()); return; } - // 消费金额就是订单总金额 - BigDecimal orderAmount = new BigDecimal(data.getConsumptionAmount()); + // 获取更新数据后的orderBasicInfo对象 + returnUpdateOrderBasicInfo(orderBasicInfo, data); + // 获取更新数据后的orderDetail对象/更新订单详情 查询订单详情 修改订单数据 + OrderDetail orderDetail = returnUpdateOrderDetail(orderBasicInfo, data); + // 更新数据库 + OrderTransactionDTO dto = new OrderTransactionDTO(); + dto.setOrderBasicInfo(orderBasicInfo); + dto.setOrderDetail(orderDetail); + transactionService.doUpdateOrder(dto); + // 需要退款的情况 + BigDecimal residue = orderBasicInfo.getRefundAmount(); + if (residue.compareTo(BigDecimal.ZERO) > 0) { + // 执行退款逻辑 + try { + refundOrder(orderBasicInfo, residue); + } catch (Exception e) { + logger.error("订单退款逻辑异常orderCode:{}", orderBasicInfo.getOrderCode(), e); + } + } + + // 将卡/vin状态解锁 + if (!StringUtils.equals("0000000000000000", data.getLogicCard())) { + cardStatusUnlocked(orderBasicInfo.getLogicCard()); + } + + // 如果是vin启动,将启动锁定状态改为正常 + if (StringUtils.equals(data.getTransactionIdentifier(), "05")) { + vinStatusUnlocked(data.getVinCode()); + } + + // 发送停止充电订阅消息 + sendMsg(orderBasicInfo); + + // 从redis中取出实时记录保存到表中 + realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode()); + + // TODO 如果该站点的停车场优惠券信息配置不为空,则需绑定一张优惠券 + + logger.info("结算订单end:{} OrderTransactionDTO:{}", orderBasicInfo.getOrderCode(), JSONObject.toJSONString(dto)); + } + + /** + * 返回更新后的OrderBasicInfo对象 + * 专用方法,其他地方如果要用请仔细检查 + */ + private void returnUpdateOrderBasicInfo(OrderBasicInfo orderBasicInfo, TransactionRecordsData data) { + // 订单编号 + String orderCode = orderBasicInfo.getOrderCode(); + // 消费金额就是订单总金额/交易记录传过来的消费金额 + BigDecimal orderAmount = new BigDecimal(data.getConsumptionAmount()); // 付款金额 - 实际消费金额,如果有剩余,需要走退款操作 当使用余额支付时payAmount = principalPay + giftPay BigDecimal payAmount = orderBasicInfo.getPayAmount(); @@ -705,7 +750,6 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { logger.info("结算订单:【{}】充电桩传来的消费金额:【{}】大于付款金额:【{}】, 消费金额设置为付款金额相等数据", orderCode, orderAmount, payAmount); orderAmount = payAmount; } - orderBasicInfo.setOrderAmount(orderAmount); // 订单总金额 // 虚拟金额 指订单消费中不参与结算的部分 @@ -717,14 +761,6 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { // 剩余需要退回的金额 residue BigDecimal residue = payAmount.subtract(orderAmount); - if (residue.compareTo(BigDecimal.ZERO) > 0) { - // 执行退款逻辑 - try { - refundOrder(orderBasicInfo, residue); - } catch (Exception e) { - logger.error("订单退款逻辑异常orderCode:{}", orderCode, e); - } - } // 把交易记录中的用电量,金额等信息 更新到orderBasicInfo和orderDetail orderBasicInfo.setVirtualAmount(virtualAmount); // 虚拟金额 @@ -733,7 +769,16 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { orderBasicInfo.setReason(data.getStopReasonMsg()); // 充电停止原因 orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); // 结算时间 orderBasicInfo.setRefundAmount(residue); // 结算退款金额 + } + /** + * 获取更新数据后的orderDetail对象 + * 专用方法,其他地方如果要用请仔细检查 + * @return 查询并更新过数据的orderDetail + */ + private OrderDetail returnUpdateOrderDetail(OrderBasicInfo orderBasicInfo, TransactionRecordsData data) { + String orderCode = orderBasicInfo.getOrderCode(); + BigDecimal orderAmount = orderBasicInfo.getOrderAmount(); // 更新订单详情 查询订单详情 修改订单数据 OrderDetail orderDetail = getOrderDetailByOrderCode(orderCode); try { @@ -811,30 +856,7 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { } catch (Exception e) { logger.error("设置订单详情参数发生异常", e); } - - OrderTransactionDTO dto = new OrderTransactionDTO(); - dto.setOrderBasicInfo(orderBasicInfo); - dto.setOrderDetail(orderDetail); - transactionService.doUpdateOrder(dto); - logger.info("结算订单end:{} OrderTransactionDTO:{}", orderCode, JSONObject.toJSONString(dto)); - - // 将卡/vin状态解锁 - if (!StringUtils.equals("0000000000000000", data.getLogicCard())) { - cardStatusUnlocked(orderBasicInfo.getLogicCard()); - } - - // 如果是vin启动,将启动锁定状态改为正常 - if (StringUtils.equals(data.getTransactionIdentifier(), "05")) { - vinStatusUnlocked(data.getVinCode()); - } - - // 发送停止充电订阅消息 - sendMsg(orderBasicInfo); - - // 从redis中取出实时记录保存到表中 - realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderCode); - - // TODO 如果该站点的停车场优惠券信息配置不为空,则需绑定一张优惠券 + return orderDetail; } /** @@ -944,9 +966,9 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { this.weChatRefund(applyRefundDTO); } else if (StringUtils.equals(transactionRecord.getPaymentInstitutions(), PaymentInstitutionsEnum.ADAPAY.getValue())) { // 汇付退款需要一级运营商的小程序appId, 否则会退款失败 - PileMerchantInfo pileMerchantInfo = pileMerchantInfoService.selectPileMerchantInfoById(orderBasicInfo.getMerchantId()); - if (pileMerchantInfo != null) { - applyRefundDTO.setWechatAppId(pileMerchantInfo.getAppId()); + String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId()); + if (StringUtils.isNotBlank(wechatAppId)) { + applyRefundDTO.setWechatAppId(wechatAppId); } this.refundOrderWithAdapay(applyRefundDTO); } @@ -1174,21 +1196,28 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { for (BalanceDeductionAmountVO vo : list) { String paymentId = vo.getPaymentId(); BigDecimal deductionAmount = vo.getDeductionAmount(); - // 调汇付的分账接口 确认交易 - PaymentConfirmResponse paymentConfirmResponse = adapayService.createPaymentConfirmRequest(paymentId, adapayMemberAccount, deductionAmount, orderCode, wechatAppId); - if (paymentConfirmResponse != null && paymentConfirmResponse.isNotFailed()) { - confirmAmt = confirmAmt.add(new BigDecimal(paymentConfirmResponse.getConfirmed_amt())); - feeAmt = feeAmt.add(new BigDecimal(paymentConfirmResponse.getFee_amt())); - status = paymentConfirmResponse.getStatus(); - description = paymentConfirmResponse.getDescription(); + String delayMode = vo.getDelayMode(); - // 更新这笔交易的剩余金额 - MemberAdapayRecord record = memberAdapayRecordService.selectByPaymentId(paymentId); - // 更新此笔交易单的消费金额 = 历史消费金额 + 本次消费金额 - record.setSpendAmt(record.getSpendAmt().add(deductionAmount)); - // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - record.setBalanceAmt(record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt())); - memberAdapayRecordService.updateByPrimaryKeySelective(record); + if (StringUtils.equals(delayMode, Constants.ADAPAY_PAY_MODE_DELAY)) { + // 延时分账,使用确认交易API + PaymentConfirmResponse paymentConfirmResponse = adapayService.createPaymentConfirmRequest(paymentId, adapayMemberAccount, deductionAmount, orderCode, wechatAppId); + if (paymentConfirmResponse != null && paymentConfirmResponse.isNotFailed()) { + confirmAmt = confirmAmt.add(new BigDecimal(paymentConfirmResponse.getConfirmed_amt())); + feeAmt = feeAmt.add(new BigDecimal(paymentConfirmResponse.getFee_amt())); + status = paymentConfirmResponse.getStatus(); + description = paymentConfirmResponse.getDescription(); + + // 更新这笔交易的剩余金额 + MemberAdapayRecord record = memberAdapayRecordService.selectByPaymentId(paymentId); + // 更新此笔交易单的消费金额 = 历史消费金额 + 本次消费金额 + record.setSpendAmt(record.getSpendAmt().add(deductionAmount)); + // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 + record.setBalanceAmt(record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt())); + memberAdapayRecordService.updateByPrimaryKeySelective(record); + } + } else { + // 实时分账 + logger.info("实时分账"); } } @@ -1219,7 +1248,13 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { BigDecimal balanceAmt = memberAdapayRecord.getBalanceAmt(); // 该笔支付扣除金额 BigDecimal deductionAmount; - + // 获取延时分账模式 延时分账的使用撤销方法退款,实时分账的使用退款方法 + AdapayCallbackRecord callbackRecord = adapayCallbackRecordService.selectByPaymentId(memberAdapayRecord.getPaymentId()); + String payMode = null; + if (callbackRecord != null) { + JSONObject expendJsonObject = JSON.parseObject(callbackRecord.getExpend()); + payMode = expendJsonObject.getString("payMode"); + } // 消费金额 - 剩余金额 tempAmount = tempAmount.subtract(balanceAmt); if (tempAmount.compareTo(BigDecimal.ZERO) >= 0) { @@ -1229,6 +1264,7 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { .memberId(memberId) .paymentId(memberAdapayRecord.getPaymentId()) .deductionAmount(deductionAmount) + .delayMode(payMode) .build(); resultList.add(build); } else { @@ -1238,6 +1274,7 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { .memberId(memberId) .paymentId(memberAdapayRecord.getPaymentId()) .deductionAmount(deductionAmount) + .delayMode(payMode) .build(); resultList.add(build); break; @@ -2321,7 +2358,7 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { /** * 汇付支付-订单退款处理逻辑 - * + * 汇付支付订单退款 * @param dto */ @Override @@ -2343,7 +2380,7 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR); } - // 拿orderCode查询延时分账模式 延时分账的使用撤销方法退款,实时分账的使用退款方法 + // 获取延时分账模式 延时分账的使用撤销方法退款,实时分账的使用退款方法 String expend = callbackRecord.getExpend(); JSONObject expendJsonObject = JSON.parseObject(expend); String payMode = expendJsonObject.getString("payMode"); @@ -2417,8 +2454,13 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { // } } + /** + * 汇付支付余额退款 + * @param dto + */ @Override public void refundBalanceWithAdapay(ApplyRefundDTO dto){ + // 做个拦截,如果前一笔退款没有完成,就抛异常 String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + dto.getMemberId(); PaymentReverseResponse redisResult = redisCache.getCacheObject(redisKey); if (Objects.nonNull(redisResult)) { @@ -2438,9 +2480,6 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR); } - // 模拟放缓存 - // redisCache.setCacheObject(redisKey, new PaymentReverseResponse(), CacheConstants.cache_expire_time_30m); - // 查询用户充值余额订单 过滤掉已经退款的充值订单 List list = calculateTheBalanceDeductionAmount(dto.getMemberId(), refundAmount); for (BalanceDeductionAmountVO vo : list) { diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/vo/web/BalanceDeductionAmountVO.java b/jsowell-pile/src/main/java/com/jsowell/pile/vo/web/BalanceDeductionAmountVO.java index e369517e8..9a20750cf 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/vo/web/BalanceDeductionAmountVO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/vo/web/BalanceDeductionAmountVO.java @@ -24,4 +24,10 @@ public class BalanceDeductionAmountVO { * 扣除金额 */ private BigDecimal deductionAmount; + + /** + * 该笔支付单的分账方式 + * delay表示延时分账,其他情况表示实时分账 + */ + private String delayMode; }