一、步骤
controller
//取消预约
@PostMapping("auth/cancel0rder/{orderId}")
public Result cancel0rder(@PathVariable Long orderId) {
Boolean isOrder = orderService.cancel0rder(orderId);
return Result.ok(isOrder);
}
OrderServiceImpl:
//取消预约
@Override
public Boolean cancel0rder(Long orderId) {
//1、根据id查询订单信息
OrderInfo orderInfo = baseMapper.selectById(orderId);
if (orderInfo == null){
return false;
}
//2、判断当前时间是否在退款时间之前
DateTime dateTime = new DateTime(orderInfo.getQuitTime());
if(dateTime.isBeforeNow()){ // 退款时间在当前时间之前 ==>超过了退款时间
throw new YyghException(ResultCodeEnum.CANCEL_ORDER_NO);
}
//3、通过医院远程服务 取消预约
SignInfoVo signInfoVo = hospitalFeignClient.getSignInfoVo(orderInfo.getHoscode());//获取签名 和 api基础路径
if(null == signInfoVo) {
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
Map<String, Object> reqMap = new HashMap<>();
reqMap.put("hoscode",orderInfo.getHoscode());
reqMap.put("hosRecordId",orderInfo.getHosRecordId());
reqMap.put("timestamp", HttpRequestHelper.getTimestamp());
String sign = HttpRequestHelper.getSign(reqMap, signInfoVo.getSignKey());
reqMap.put("sign", sign);
//"http://localhost:9998/order/submitOrder"
JSONObject result = HttpRequestHelper.sendRequest(reqMap, "http://localhost:9998/order/updateCancelStatus");
System.out.println("result" + result);
if (result.getInteger("code") == 200){ //请求成功
//4、根据支付状态 判断书否可以退款
if (orderInfo.getOrderStatus().intValue() == OrderStatusEnum.PAID.getStatus().intValue()){ // 已支付 可以退款
//调用退款功能
Boolean isRefund = weixinService.refund(orderId);
if(!isRefund) {
throw new YyghException(ResultCodeEnum.CANCEL_ORDER_FAIL);
}
//更新订单状态
orderInfo.setOrderStatus(OrderStatusEnum.CANCLE.getStatus());
baseMapper.updateById(orderInfo);
//发送mq信息更新预约数 我们与下单成功更新预约数使用相同的mq信息,不设置可预约数与剩余预约数,接收端可预约数减1即可
OrderMqVo orderMqVo = new OrderMqVo();
orderMqVo.setScheduleId(orderInfo.getScheduleId());
//短信提示
MsmVo msmVo = new MsmVo();
msmVo.setPhone(orderInfo.getPatientPhone());
msmVo.setTemplateCode("SMS_220545305");
String reserveDate = new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd") + (orderInfo.getReserveTime()==0 ? "上午": "下午");
Map<String,Object> param = new HashMap<String,Object>(){{
put("title", orderInfo.getHosname()+"|"+orderInfo.getDepname()+"|"+orderInfo.getTitle());
put("reserveDate", reserveDate);
put("name", orderInfo.getPatientName());
}};
msmVo.setParam(param);
orderMqVo.setMsmVo(msmVo);
rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER, MqConst.ROUTING_ORDER, orderMqVo);
return true;
}
}else {
throw new YyghException(result.getString("message"), ResultCodeEnum.FAIL.getCode());
}
return false;
}
1、根据id查询订单信息
2、判断当前时间是否在退款时间之前
3、通过医院远程服务 取消预约
4、根据支付状态 判断书否可以退款
/***
* 调用微信接口 退款
*/
@Transactional(rollbackFor=Exception.class)
@Override
public Boolean refund(Long orderId) {
try {
//1、获取支付记录
PaymentInfo paymentInfo = paymentService.getPaymentInfo(orderId, PaymentTypeEnum.WEIXIN.getStatus());
if (paymentInfo == null) {//没有支付记录 退款失败
return false;
}
//2、添加支付记录到退款记录
RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfo);
//判断当前订单数据是否已经退款
if (refundInfo.getRefundStatus().intValue() == RefundStatusEnum.REFUND.getStatus().intValue()) {
return true;
}
//3、调用微信接口 执行退款操作
Map<String, String> paramMap = new HashMap<>(8);
paramMap.put("appid", ConstantPropertiesUtils.APPID); //公众账号ID
paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER); //商户编号
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("transaction_id", paymentInfo.getTradeNo()); //微信订单号
paramMap.put("out_trade_no", paymentInfo.getOutTradeNo()); //商户订单编号
paramMap.put("out_refund_no", "tk" + paymentInfo.getOutTradeNo()); //商户退款单号
//paramMap.put("total_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
//paramMap.put("refund_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
paramMap.put("total_fee", "1");
paramMap.put("refund_fee", "1"); //退款金额
String paramXml = WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY);
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
client.setXmlParam(paramXml);
client.setHttps(true);
//设置证书
client.setCert(true);
client.setCertPassword(ConstantPropertiesUtils.PARTNER);//退款路径
client.post();
//4、返回第三方的数据
String xml = client.getContent();
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
if (null != resultMap && WXPayConstants.SUCCESS.equalsIgnoreCase(resultMap.get("result_code"))) {
refundInfo.setCallbackTime(new Date());
refundInfo.setTradeNo(resultMap.get("refund_id"));
refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());//退款状态
refundInfo.setCallbackContent(JSONObject.toJSONString(resultMap));
refundInfoService.updateById(refundInfo);
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
5、发送mq信息更新预约数
hospital监听
package com.atguigu.yygh.receiver;
import com.atguigu.common.rabbit.constant.MqConst;
import com.atguigu.common.rabbit.service.RabbitService;
import com.atguigu.yygh.model.hosp.Schedule;
import com.atguigu.yygh.service.ScheduleService;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class HospitalReceiver {
@Autowired
private ScheduleService scheduleService;
@Autowired
private RabbitService rabbitService;
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = MqConst.QUEUE_ORDER, durable = "true"),
exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_ORDER),
key = {MqConst.ROUTING_ORDER}
))
public void receiver(OrderMqVo orderMqVo, Message message, Channel channel) throws IOException {
if(null != orderMqVo.getAvailableNumber()) {
//下单成功更新预约数
Schedule schedule = (Schedule) scheduleService.getById(orderMqVo.getScheduleId());
schedule.setReservedNumber(orderMqVo.getReservedNumber());
schedule.setAvailableNumber(orderMqVo.getAvailableNumber());
scheduleService.update(schedule);
} else {
//取消预约更新预约数
Schedule schedule = (Schedule) scheduleService.getById(orderMqVo.getScheduleId());
int availableNumber = schedule.getAvailableNumber().intValue() + 1;
schedule.setAvailableNumber(availableNumber);
scheduleService.update(schedule);
}
//发送短信
MsmVo msmVo = orderMqVo.getMsmVo();
if(null != msmVo) {
rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM, MqConst.ROUTING_MSM_ITEM, msmVo);
}
}
}
三、证书
service-order : properties
package com.atguigu.yygh.order.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ConstantPropertiesUtils implements InitializingBean {
@Value("${weixin.cert}")
private String cert;
@Value("${weixin.appid}")
private String appid;
@Value("${weixin.partner}")
private String partner;
@Value("${weixin.partnerkey}")
private String partnerkey;
public static String APPID;
public static String PARTNER;
public static String PARTNERKEY;
public static String CERT;
@Override
public void afterPropertiesSet() throws Exception {
APPID = appid;
PARTNER = partner;
PARTNERKEY = partnerkey;
CERT = cert;
}
}