医生App端医生拒接专家咨询订单接口开发

This commit is contained in:
纪寒 2023-10-19 16:52:34 +08:00
parent 2a85d219fd
commit 82ec747dc4
10 changed files with 197 additions and 83 deletions

View File

@ -3,6 +3,7 @@ package com.xinelu.applet.controller.wechatpaymentinfo;
import com.xinelu.applet.service.wechatpaymentinfo.WeChatPayNotifyService;
import com.xinelu.applet.service.wechatpaymentinfo.WeChatPaymentService;
import com.xinelu.applet.service.wechatpaymentinfo.WeChatRefundService;
import com.xinelu.applet.vo.wechatpaymentinfo.dto.CloseOrderDTO;
import com.xinelu.applet.vo.wechatpaymentinfo.dto.PaymentDTO;
import com.xinelu.applet.vo.wechatpaymentinfo.dto.RefundDTO;
import com.xinelu.common.annotation.MobileRequestAuthorization;
@ -105,19 +106,6 @@ public class WeChatPaymentController extends BaseController {
return weChatPayNotifyService.xylWeChatPayNotify(request, response);
}
/**
* 医路优品微信支付回调通知接口
*
* @param request 请求头信息
* @param response 响应信息
* @return 应答信息避免微信平台重复发送回调通知
* @throws Exception 异常信息
*/
@PostMapping("/ylypWeChatPayNotify")
public String ylypWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
return weChatPayNotifyService.ylypWeChatPayNotify(request, response);
}
/**
* 微信确认退款接口
*
@ -143,16 +131,13 @@ public class WeChatPaymentController extends BaseController {
}
/**
* 医路优品微信退款回调通知接口
* 专家咨询订单-医生端App拒单接口
*
* @param request 请求头信息
* @param response 响应信息
* @return 应答信息避免微信平台重复发送回调通知
* @throws Exception 异常信息
* @param closeOrderDTO 订单关闭参数
* @return 退款申请结果
*/
@PostMapping("/ylypWeChatRefundNotify")
public String ylypWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
return weChatPayNotifyService.ylypWeChatRefundNotify(request, response);
@PostMapping("/closeHealthConsultationOrder")
public AjaxResult closeHealthConsultationOrder(@Validated(Insert.class) @RequestBody CloseOrderDTO closeOrderDTO) {
return weChatRefundService.closeHealthConsultationOrder(closeOrderDTO);
}
}

View File

@ -21,16 +21,6 @@ public interface WeChatPayNotifyService {
*/
String xylWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception;
/**
* 医路优品支付回调接口
*
* @param request 请求信息
* @param response 响应信息
* @return 应答信息避免微信平台重复发送回调通知
* @throws Exception 异常信息
*/
String ylypWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception;
/**
* 新医路退款回调接口
*
@ -40,14 +30,4 @@ public interface WeChatPayNotifyService {
* @throws Exception 异常信息
*/
String xylWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception;
/**
* 医路优品退款回调接口
*
* @param request 请求信息
* @param response 响应信息
* @return 应答信息避免微信平台重复发送回调通知
* @throws Exception 异常信息
*/
String ylypWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

View File

@ -1,5 +1,6 @@
package com.xinelu.applet.service.wechatpaymentinfo;
import com.xinelu.applet.vo.wechatpaymentinfo.dto.CloseOrderDTO;
import com.xinelu.applet.vo.wechatpaymentinfo.dto.RefundDTO;
import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatRefundInfoVO;
import com.xinelu.common.core.domain.AjaxResult;
@ -36,4 +37,12 @@ public interface WeChatRefundService {
* @return 退款信息
*/
WeChatRefundInfoVO queryGoodsOrderRefundStatus(String refundNo, String buySource);
/**
* 专家咨询订单-医生端App拒单接口
*
* @param closeOrderDTO 订单关闭参数
* @return 返回信息
*/
AjaxResult closeHealthConsultationOrder(CloseOrderDTO closeOrderDTO);
}

View File

@ -105,20 +105,6 @@ public class WeChatPayNotifyServiceImpl implements WeChatPayNotifyService {
return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.XINYILU.getInfo(), PAY);
}
/**
* 医路优品支付回调接口
*
* @param request 请求信息
* @param response 响应信息
* @return 应答信息避免微信平台重复发送回调通知
* @throws Exception 异常信息
*/
@Override
public String ylypWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
log.info("医路优品微信支付回调开始执行");
return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.YILUYOUPIN.getInfo(), PAY);
}
/**
* 新医路退款回调接口
*
@ -133,20 +119,6 @@ public class WeChatPayNotifyServiceImpl implements WeChatPayNotifyService {
return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.XINYILU.getInfo(), REFUND);
}
/**
* 医路优品退款回调接口
*
* @param request 请求信息
* @param response 响应信息
* @return 应答信息避免微信平台重复发送回调通知
* @throws Exception 异常信息
*/
@Override
public String ylypWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
log.info("医路优品微信退款回调开始执行");
return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.YILUYOUPIN.getInfo(), REFUND);
}
/**
* 微信支付回调通知公共方法
*
@ -194,11 +166,9 @@ public class WeChatPayNotifyServiceImpl implements WeChatPayNotifyService {
resultMap.put("message", "解密失败!");
return JSON.toJSONString(resultMap);
}
//记录支付日志和修改订单状态
if (Constants.PAY_NOTIFY.equals(refundAndPaymentFlag)) {
this.processPaymentInfo(plainText);
}
//修改订单状态以及增加库存以及退还用户所使用的优惠券信息
if (Constants.REFUND_NOTIFY.equals(refundAndPaymentFlag)) {
this.processRefundInfo(plainText);
}

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.xinelu.applet.service.goodstock.GoodsStockService;
import com.xinelu.applet.service.wechatpaymentinfo.WeChatRefundService;
import com.xinelu.applet.vo.wechatpaymentinfo.dto.CloseOrderDTO;
import com.xinelu.applet.vo.wechatpaymentinfo.dto.RefundDTO;
import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatRefundInfoVO;
import com.xinelu.common.config.WeChatPaymentUrlConfig;
@ -115,7 +116,8 @@ public class WeChatRefundServiceImpl implements WeChatRefundService {
Long patientId = Objects.isNull(appointmentOrderInfo.getPatientId()) ? 0 : appointmentOrderInfo.getPatientId();
String outRefundNo = com.xinelu.common.utils.StringUtils.fillZeroByPatientId(patientId, 5) + System.nanoTime();
String refundParam = buildRefundParam(null, appointmentOrderInfo, refundDTO, outRefundNo);
this.applyWeRefund(refundParam, appointmentOrderInfo, null, patientId, refundDTO);
String refundReason = StringUtils.isBlank(refundDTO.getRefundReason()) ? "" : refundDTO.getRefundReason();
this.applyWeRefund(refundParam, appointmentOrderInfo, null, patientId, refundReason);
return AjaxResult.success();
}
GoodsOrder goodsOrderInfo = goodsOrderMapper.getGoodsOrderByOrderNo(refundDTO.getOrderNo());
@ -136,7 +138,8 @@ public class WeChatRefundServiceImpl implements WeChatRefundService {
Long patientId = Objects.isNull(goodsOrderInfo.getPatientId()) ? 0 : goodsOrderInfo.getPatientId();
String outRefundNo = com.xinelu.common.utils.StringUtils.fillZeroByPatientId(patientId, 5) + System.nanoTime();
String refundParam = buildRefundParam(goodsOrderInfo, null, refundDTO, outRefundNo);
this.applyWeRefund(refundParam, null, goodsOrderInfo, patientId, refundDTO);
String refundReason = StringUtils.isBlank(refundDTO.getRefundReason()) ? "" : refundDTO.getRefundReason();
this.applyWeRefund(refundParam, null, goodsOrderInfo, patientId, refundReason);
return AjaxResult.success();
}
return AjaxResult.success();
@ -204,6 +207,38 @@ public class WeChatRefundServiceImpl implements WeChatRefundService {
}
}
/**
* 专家咨询订单-医生端App拒单接口
*
* @param closeOrderDTO 订单关闭参数
* @return 返回信息
*/
@Transactional(rollbackFor = Exception.class)
@Override
public AjaxResult closeHealthConsultationOrder(CloseOrderDTO closeOrderDTO) {
GoodsOrder goodsOrderInfo = goodsOrderMapper.getGoodsOrderByOrderNo(closeOrderDTO.getOrderNo());
if (Objects.isNull(goodsOrderInfo) || StringUtils.isBlank(goodsOrderInfo.getOrderNo())) {
return AjaxResult.error("当前订单信息不存在,无法拒单!");
}
if (StringUtils.isBlank(goodsOrderInfo.getOrderType())
|| !StringUtils.equals(OrderTypeEnum.HEALTH_CONSULTATION.getInfo(), goodsOrderInfo.getOrderType())) {
return AjaxResult.error("当前订单非专家咨询订单,无法拒单!");
}
if (StringUtils.isBlank(goodsOrderInfo.getOrderStatus())
|| !StringUtils.equals(GooodsOrderStatusEnum.WAIT_RECEIVED_GOODS.getInfo(), goodsOrderInfo.getOrderStatus())) {
return AjaxResult.error("当前订单状态异常,无法拒单!");
}
if (Objects.isNull(goodsOrderInfo.getTotalPrice()) || goodsOrderInfo.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) {
return AjaxResult.error("当前订单金额异常,无法拒单!");
}
Long patientId = Objects.isNull(goodsOrderInfo.getPatientId()) ? 0 : goodsOrderInfo.getPatientId();
String outRefundNo = com.xinelu.common.utils.StringUtils.fillZeroByPatientId(patientId, 5) + System.nanoTime();
String refundParam = this.buildHealthConsultationRefundParam(goodsOrderInfo, outRefundNo);
String refundReason = StringUtils.isBlank(closeOrderDTO.getRemark()) ? "" : closeOrderDTO.getRemark();
this.applyWeRefund(refundParam, null, goodsOrderInfo, patientId, refundReason);
return AjaxResult.success();
}
/**
* 退款参数检验
*
@ -257,10 +292,10 @@ public class WeChatRefundServiceImpl implements WeChatRefundService {
* @param appointmentOrderInfo 预约服务订单信息
* @param goodsOrderInfo 商品订单信息
* @param patientId 会员id
* @param refundDTO 申请信息
* @param refundReason 退款原因
*/
public void applyWeRefund(String refundParam, AppointmentOrder appointmentOrderInfo,
GoodsOrder goodsOrderInfo, Long patientId, RefundDTO refundDTO) {
GoodsOrder goodsOrderInfo, Long patientId, String refundReason) {
String requestUrl = weChatPaymentUrlConfig.getRefundApplyUrl();
HttpPost httpPost = new HttpPost(requestUrl);
StringEntity entity = new StringEntity(refundParam, "utf-8");
@ -286,7 +321,7 @@ public class WeChatRefundServiceImpl implements WeChatRefundService {
WeChatRefundInfoVO weChatRefundInfoVO = JSONObject.parseObject(body, WeChatRefundInfoVO.class);
int refundInfoCount = refundInfoMapper.getRefundInfoByOrderNo(weChatRefundInfoVO.getOutTradeNo());
if (refundInfoCount <= 0) {
RefundInfo refundInfo = buildRefundInfo(patientId, weChatRefundInfoVO, refundDTO, body, refundMerchantType);
RefundInfo refundInfo = buildRefundInfo(patientId, weChatRefundInfoVO, refundReason, body, refundMerchantType);
int insertCunt = refundInfoMapper.insertRefundInfo(refundInfo);
if (insertCunt <= 0) {
throw new ServiceException("记录退款信息失败,请联系管理员!");
@ -302,19 +337,19 @@ public class WeChatRefundServiceImpl implements WeChatRefundService {
*
* @param patientId 会员id
* @param refundInfoVO 退款信息参数
* @param refundDTO 退款申请参数
* @param refundReason 退款原因
* @param refundBody 返回体
* @param refundMerchantType 退款账户类型新医路或者医路优品
*/
private RefundInfo buildRefundInfo(Long patientId, WeChatRefundInfoVO refundInfoVO,
RefundDTO refundDTO, String refundBody, String refundMerchantType) {
String refundReason, String refundBody, String refundMerchantType) {
RefundInfo refundInfo = new RefundInfo();
refundInfo.setPatientId(patientId);
refundInfo.setOrderNo(refundInfoVO.getOutTradeNo());
refundInfo.setRefundNo(refundInfoVO.getRefundId());
refundInfo.setOutRefundNo(refundInfoVO.getOutRefundNo());
refundInfo.setTransactionNo(StringUtils.isBlank(refundInfoVO.getTransactionId()) ? "" : refundInfoVO.getTransactionId());
refundInfo.setRefundReason(StringUtils.isBlank(refundDTO.getRefundReason()) ? "" : refundDTO.getRefundReason());
refundInfo.setRefundReason(refundReason);
refundInfo.setRefundType(RefundTypeEnum.WE_CHAT.getInfo());
refundInfo.setWechatRefundStatus(RefundStatusEnum.PROCESSING.getInfo());
refundInfo.setOrderTotalPrice(BigDecimal.valueOf(refundInfoVO.getAmount().getTotal()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN));
@ -393,4 +428,24 @@ public class WeChatRefundServiceImpl implements WeChatRefundService {
}
return null;
}
/**
* 构建专家咨询微信退款参数信息
*
* @param goodsOrderInfo 专家咨询订单信息
* @param outRefundNo 退款单号
* @return 退款申请Json串
*/
private String buildHealthConsultationRefundParam(GoodsOrder goodsOrderInfo, String outRefundNo) {
Map<String, Object> paramMap = new LinkedHashMap<>();
paramMap.put("out_trade_no", goodsOrderInfo.getOrderNo());
paramMap.put("out_refund_no", outRefundNo);
Map<String, Object> amountMap = new LinkedHashMap<>();
paramMap.put("notify_url", xylWeChatPaymentConfig.getXylWeChatNotifyUrl() + XINYILU_WE_CHAT_REFUND_URL);
amountMap.put("refund", goodsOrderInfo.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue());
amountMap.put("total", goodsOrderInfo.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue());
amountMap.put("currency", "CNY");
paramMap.put("amount", amountMap);
return JSON.toJSONString(paramMap);
}
}

View File

@ -0,0 +1,27 @@
package com.xinelu.applet.vo.wechatpaymentinfo.dto;
import com.xinelu.common.custominterface.Insert;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @Description 订单关闭DTO
* @Author 纪寒
* @Date 2023-10-19 14:28:07
* @Version 1.0
*/
@Data
public class CloseOrderDTO implements Serializable {
private static final long serialVersionUID = -1681680608523099847L;
/**
* 订单编号必传字段
*/
@NotBlank(message = "订单编号不能为空!", groups = {Insert.class})
private String orderNo;
/**
* 拒单原因
*/
private String remark;
}

View File

@ -1,5 +1,6 @@
package com.xinelu.quartz.controller;
import com.xinelu.quartz.task.RefundHealthConsultationOrderTask;
import com.xinelu.quartz.task.RefundInfoTask;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -19,14 +20,22 @@ public class RefundInfoTaskController {
@Resource
private RefundInfoTask refundInfoTask;
@Resource
private RefundHealthConsultationOrderTask refundHealthConsultationOrderTask;
/**
* 手动执行修改退款单状态定时任务
*
* @throws Exception 异常信息
*/
@GetMapping("/handleRefundStatus")
public void handleRefundStatus() throws Exception {
public void handleRefundStatus() {
refundInfoTask.automaticProcessRefundInfo();
}
/**
* 手动执行处理专家咨询订单医生手动拒单定时任务
*/
@GetMapping("/handleHealthConsultationStatus")
public void handleHealthConsultationRefund() {
refundHealthConsultationOrderTask.automaticProcessHealthConsultationRefund();
}
}

View File

@ -13,4 +13,9 @@ public interface RefundInfoTaskService {
* 防止由于网络等其它原因未接受到退款回调通知进而导致的退款单状态修改不及时
*/
void automaticProcessRefundInfo();
/**
* 自动处理专家咨询订单医生手动拒单定时任务
*/
void automaticProcessHealthConsultationRefund();
}

View File

@ -93,6 +93,26 @@ public class RefundInfoTaskServiceImpl implements RefundInfoTaskService {
}
}
/**
* 自动处理专家咨询订单医生手动拒单定时任务
*/
@Override
public void automaticProcessHealthConsultationRefund() {
List<RefundOrderInfoVO> refundGoodsOrderLit = goodsOrderMapper.getRefundGoodsOrderInfo(GooodsOrderStatusEnum.WAIT_RECEIVED_GOODS.getInfo(), RefundStatusEnum.PROCESSING.getInfo(), ConfirmRefundStatusEnum.CONFIRMED.getInfo());
if (CollectionUtils.isEmpty(refundGoodsOrderLit)) {
return;
}
TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
processHealthConsultationRefund(refundGoodsOrderLit);
transactionManager.commit(transactionStatus);
} catch (Exception e) {
transactionManager.rollback(transactionStatus);
log.error("处理专家咨询订单医生手动拒单定时任务异常,异常信息 =====> {}", e.getMessage());
throw e;
}
}
/**
* 处理退款的预约订单信息
*
@ -158,4 +178,28 @@ public class RefundInfoTaskServiceImpl implements RefundInfoTaskService {
}
}
/**
* 处理退款成功的专家咨询订单信息
*
* @param refundGoodsOrderLit 专家咨询订单信息
*/
private void processHealthConsultationRefund(List<RefundOrderInfoVO> refundGoodsOrderLit) {
List<String> orderNoList = Lists.newArrayList();
for (RefundOrderInfoVO refundOrderInfoVO : refundGoodsOrderLit) {
if (StringUtils.isBlank(refundOrderInfoVO.getOrderNo())
|| StringUtils.isBlank(refundOrderInfoVO.getOutRefundNo()) || StringUtils.isBlank(refundOrderInfoVO.getBuySource())) {
continue;
}
WeChatRefundInfoVO weChatRefundInfoVO = weChatRefundService.queryGoodsOrderRefundStatus(refundOrderInfoVO.getOutRefundNo(), refundOrderInfoVO.getBuySource());
if (StringUtils.isNotBlank(weChatRefundInfoVO.getStatus())
&& RefundStatusEnum.SUCCESS.getInfo().equals(weChatRefundInfoVO.getStatus())) {
orderNoList.add(refundOrderInfoVO.getOrderNo());
}
LocalDateTime successTime = StringUtils.isBlank(weChatRefundInfoVO.getSuccessTime()) ? LocalDateTime.now() : LocalDateTime.parse(weChatRefundInfoVO.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME);
refundInfoMapper.updateBatchRefundStatus(refundOrderInfoVO.getOrderNo(), successTime, weChatRefundInfoVO.getStatus());
}
if (CollectionUtils.isNotEmpty(orderNoList)) {
goodsOrderMapper.updateBatchGoodsOrderStatus(orderNoList, OrderStatusEnum.REFUNDED.getInfo());
}
}
}

View File

@ -0,0 +1,30 @@
package com.xinelu.quartz.task;
import com.xinelu.quartz.service.RefundInfoTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @Description
* @Author 纪寒
* @Date 2022-10-25 14:35:59
* @Version 1.0
*/
@Slf4j
@Component("refundHealthConsultationOrderTask")
public class RefundHealthConsultationOrderTask {
@Resource
private RefundInfoTaskService refundInfoTaskService;
/**
* 自动处理专家咨询订单医生手动拒单定时任务
*/
public void automaticProcessHealthConsultationRefund() {
log.info("开始执行专家咨询订单医生手动拒单定时任务........");
refundInfoTaskService.automaticProcessHealthConsultationRefund();
log.info("完成专家咨询订单医生手动拒单定时任务........");
}
}