package com.ltkj.web.controller.mall; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.google.common.base.Joiner; import com.ltkj.common.core.domain.AjaxResult; import com.ltkj.common.exception.user.DataNotFoundException; import com.ltkj.common.task.TaskService; import com.ltkj.common.utils.IpUtil; import com.ltkj.common.utils.JacksonUtil; import com.ltkj.framework.config.UserHoder; import com.ltkj.hosp.domain.*; import com.ltkj.hosp.service.*; import com.ltkj.mall.domain.*; import com.ltkj.mall.mallOrderUtils.OrderConstants; import com.ltkj.mall.service.*; import com.ltkj.mall.mallOrderUtils.OrderHandleOption; import com.ltkj.mall.mallOrderUtils.OrderUtil; import com.ltkj.system.service.ISysConfigService; import com.ltkj.web.config.redis.OrderDelayService; import com.ltkj.web.wxUtils.WxUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.aspectj.bridge.MessageWriter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.validation.constraints.NotNull; import java.io.IOException; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; /** * @Company: 西安路泰科技有限公司 * @Author: lige * @Date: 2023/7/13 15:16 */ @RestController @RequestMapping("/cus/order") @Validated @Api(tags = "体检小程序订单接口") @Slf4j public class WxMallOrderController { @Resource private ITjReservationService reservationService; @Resource private ITjProjectService projectService; @Resource private ITjPackageProjectService ppservice; @Autowired private IMallOrderService orderService; @Autowired private IMallAftersaleService mallAftersaleService; @Resource private IMallOrderGoodsService orderGoodsService; @Autowired private IMallCartService mallCartService; @Autowired private ITjPackageService packageService; @Autowired private WxPayService wxPayService; @Resource private ITbTransitionService transitionService; @Autowired private TaskService taskService; @Resource private OrderDelayService delayService; @Autowired private IMallTimeConfigService mallTimeConfigService; @Resource private ISysConfigService configService; @Value("${wx.pay.pay-score-notify-url}") private String notifyUrl; @GetMapping("/isPay") @ApiOperation(value = "小程序端是否开启支付接口(true开启 false 关闭)") public AjaxResult isPay() { String isPays = configService.selectConfigByKey("isPay"); return AjaxResult.success(isPays); } /** * 订单列表 * @param showType 显示类型,如果是0则是全部订单 1未付款订单 2待核销订单 3已完成订单 * @return 订单列表 */ @GetMapping("/list") @ApiOperation(value = "订单列表") public AjaxResult list(@RequestParam(defaultValue = "0") Integer showType) { Wxuser wxuser = UserHoder.getWxuser(); if (null != wxuser) { List orderStatus = OrderUtil.orderStatus(showType); LambdaQueryWrapper wq = new LambdaQueryWrapper() .eq(null != wxuser.getId() && 0 != wxuser.getId(), MallOrder::getUserId, wxuser.getId()) .in(CollectionUtil.isNotEmpty(orderStatus), MallOrder::getOrderStatus, orderStatus) .orderByDesc(MallOrder::getCreateTime); List orderList = orderService.list(wq); if(null !=orderList && orderList.size()>0){ for (MallOrder order : orderList) { TjReservation reservation = reservationService.getById(order.getReservationId()); if(null !=reservation){ LambdaQueryWrapper wq1 = new LambdaQueryWrapper<>(); wq1.eq(MallOrderGoods::getOrderId, order.getId()); order.setMallOrderGoodsList(orderGoodsService.list(wq1)); order.setReservationTime(reservation.getReservationTime()); if(null !=reservation.getPacId()){ order.setPacId(reservation.getPacId()); TjPackage tjPackageByPacId = packageService.getTjPackageByPacId(reservation.getPacId()); if(null !=tjPackageByPacId){ order.setPacName(packageService.getTjPackageByPacId(reservation.getPacId()).getPacName()); } } } } } return AjaxResult.success(orderList); } return AjaxResult.error(); } /** * 订单详情 * * @param orderId 订单ID * @return 订单详情 */ @GetMapping("/detailByOrderId") @ApiOperation(value = "订单详情") public AjaxResult detailByOrderId(@RequestParam Integer orderId) { Wxuser wxuser = UserHoder.getWxuser(); if (null != wxuser) { LambdaQueryWrapper wq = new LambdaQueryWrapper<>(); wq.eq(MallOrderGoods::getOrderId, orderId); final List list = orderGoodsService.list(wq); // if(null !=list && list.size()>0){ // for (MallOrderGoods orderGoods : list) { // TjPackage aPackage = packageService.getById(orderGoods.getGoodsId()); // if(null !=aPackage){ // List pplist = ppservice.getTjPackageProjectListByPacId(String.valueOf(orderGoods.getGoodsId())); // for (TjPackageProject project : pplist) { // project.setProName(projectService.getById(project.getProId()).getProName()); // } // } // } // } return AjaxResult.success(list); } return AjaxResult.error(); } /** * 提交订单 * * @return 提交订单操作结果 */ @Transactional @PostMapping("/submit") @ApiOperation(value = "提交订单") public Object submit(@RequestBody Map map) { Wxuser wxuser = UserHoder.getWxuser(); Object reservationId = map.get("reservationId"); Object price = map.get("price"); if (null == wxuser) { return AjaxResult.error(); } if (reservationId == null) { return AjaxResult.error(); } TjReservation reservation = reservationService.getById(reservationId.toString()); if (reservation == null) { return AjaxResult.error(); } // 订单 MallOrder order = new MallOrder(); order.setUserId(wxuser.getId()); order.setReservationId(String.valueOf(reservationId)); order.setOrderSn("TJ"+wxuser.getId().toString().substring(wxuser.getId().toString().length()-4) + new SimpleDateFormat("yyMMddHHmmss").format(new Date())); order.setOrderStatus(Long.valueOf(OrderUtil.STATUS_CREATE)); order.setConsignee(reservation.getName()); order.setMobile(reservation.getPhoe()); order.setIdCard(reservation.getIdCard()); if(null !=map.get("message")){ order.setMessage(map.get("message").toString()); } order.setAddress(reservation.getAddress()); if(null !=price){ BigDecimal goodsPrice = new BigDecimal(price.toString()); order.setGoodsPrice(goodsPrice); order.setOrderPrice(goodsPrice); order.setActualPrice(goodsPrice); }else { order.setGoodsPrice(transitionService.sumNowPrice(reservation.getIdCard())); order.setOrderPrice(transitionService.sumNowPrice(reservation.getIdCard())); order.setActualPrice(transitionService.sumNowPrice(reservation.getIdCard())); } order.setCreateTime(new Date()); order.setUpdateTime(new Date()); // 添加订单表项 orderService.save(order); // 添加订单商品表项 if(null != reservation.getPacId()){ TjPackage tjPackage = packageService.getTjPackageByPacId(String.valueOf(reservation.getPacId())); // 订单商品 List pplist = ppservice.getTjPackageProjectListByPacId(String.valueOf(reservation.getPacId())); for (TjPackageProject project : pplist) { TjProject byId = projectService.getById(project.getProId()); MallOrderGoods orderGoods = new MallOrderGoods(); orderGoods.setOrderId(order.getId()); orderGoods.setGoodsId(project.getProId()); orderGoods.setGoodsName(byId.getProName()); orderGoods.setPrice(project.getPriceNow()); orderGoods.setNumber(1L); orderGoods.setCreateTime(new Date()); // orderGoods.setPicUrl(tjPackage.getPacPhone()); orderGoodsService.save(orderGoods); } // 删除购物车里面的商品信息 this.mallCartService.remove(new LambdaUpdateWrapper() .eq(MallCart::getUserId, wxuser.getId()).eq(MallCart::getGoodsId,reservation.getPacId()) ); } if(null !=reservation.getProIds()){ String[] split = reservation.getProIds().split(","); for (String s : split) { TjProject project = projectService.getById(s); // 订单商品 MallOrderGoods orderGoods = new MallOrderGoods(); orderGoods.setOrderId(order.getId()); orderGoods.setGoodsId(Long.valueOf(s)); orderGoods.setGoodsName(project.getProName()); orderGoods.setPrice(project.getProPrice()); orderGoods.setNumber(1L); orderGoods.setCreateTime(new Date()); orderGoodsService.save(orderGoods); // 删除购物车里面的商品信息 this.mallCartService.remove(new LambdaUpdateWrapper() .eq(MallCart::getUserId, wxuser.getId()).eq(MallCart::getGoodsId,s) ); } } // 订单支付超期任务 delayService.produce(String.valueOf(order.getId())); Map data = new HashMap<>(); data.put("orderId",order.getId()); return AjaxResult.success(data); } /** * 取消订单 * * @param body 订单信息,{ orderId:xxx } * @return 取消订单操作结果 * * 1. 检测当前订单是否能够取消; * * 2. 设置订单取消状态; */ @PostMapping("/cancel") @Transactional @ApiOperation(value = "取消订单") public Object cancel(@RequestBody String body) { Wxuser wxuser = UserHoder.getWxuser(); if (null == wxuser) { return AjaxResult.error(); } Long orderId = JacksonUtil.parseLong(body, "orderId"); if (orderId == null) { return AjaxResult.error(); } MallOrder order = orderService.getById(orderId); if (order == null) { return AjaxResult.error(); } // 检测是否能够取消 OrderHandleOption handleOption = OrderUtil.build(order); if (!handleOption.isCancel()) { return AjaxResult.error("订单不能取消"); } // 设置订单已取消状态 order.setOrderStatus(OrderUtil.STATUS_CANCEL.longValue()); order.setCloseTime(new Date()); order.setUpdateTime(new Date()); orderService.updateById(order); //对应预约时间数量 final TjReservation byId = reservationService.getById(order.getReservationId()); final Date reservationTime = byId.getReservationTime(); LambdaQueryWrapper wq=new LambdaQueryWrapper<>(); wq.eq(MallTimeConfig::getTime,reservationTime); final MallTimeConfig one = mallTimeConfigService.getOne(wq); one.setNowNum(one.getNowNum()+1); mallTimeConfigService.updateById(one); byId.setIsExpire(1); reservationService.updateById(byId); transitionService.deletedTbTransitionByCusId(byId.getIdCard()); return AjaxResult.success(); } /** * 付款订单的预支付会话标识 * * @param body 订单信息,{ orderId:xxx } * @return 支付订单ID */ @PostMapping("/prepay") @Transactional @ApiOperation(value = "预支付订单接口") public Object prepay(@RequestBody Map body, HttpServletRequest request) { Object orderId = body.get("orderId"); if (orderId == null) { return AjaxResult.error(); } MallOrder order = orderService.getById(Integer.valueOf(orderId.toString())); Wxuser wxuser = UserHoder.getWxuser(); if (null == wxuser) { return AjaxResult.error(); } // Integer orderId = JacksonUtil.parseInteger(body, "orderId"); if (order == null) { return AjaxResult.error(); } if (order.getUserId().intValue() != wxuser.getId().intValue()) { return AjaxResult.error(); } // 检测是否能够取消 OrderHandleOption handleOption = OrderUtil.build(order); if (!handleOption.isPay()) { return AjaxResult.error("订单不能支付"); } String openid = wxuser.getOpenid(); if (openid == null) { return AjaxResult.error("订单不能支付"); } WxPayMpOrderResult result = null; try { WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest(); orderRequest.setOutTradeNo(order.getOrderSn()); orderRequest.setOpenid(openid); orderRequest.setBody("订单:" + order.getOrderSn()); // 元转成分 int fee = 0; BigDecimal actualPrice = order.getActualPrice(); if(null !=actualPrice){ fee = actualPrice.multiply(new BigDecimal(100)).intValue(); } orderRequest.setTotalFee(fee); orderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request)); orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI); orderRequest.setNotifyUrl(notifyUrl); result = wxPayService.createOrder(orderRequest); // 取消订单超时未支付任务 delayService.produce(String.valueOf(order.getId())); } catch (Exception e) { e.printStackTrace(); return AjaxResult.error("订单不能支付"); } return AjaxResult.success(result); } /** * 微信付款成功或失败回调接口 *

* 注意,这里pay-notify是示例地址,建议开发者应该设立一个隐蔽的回调地址 * * @param request 请求内容 * @return 操作结果 */ @ApiOperation("支付回调接口") @PostMapping("/pay-notify") @Transactional public Object payNotify(HttpServletRequest request) { String xmlResult = null; try { xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding()); } catch (IOException e) { e.printStackTrace(); return WxPayNotifyResponse.fail(e.getMessage()); } WxPayOrderNotifyResult result = null; try { result = wxPayService.parseOrderNotifyResult(xmlResult); if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())){ throw new WxPayException("微信通知支付失败!"); } if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())){ throw new WxPayException("微信通知支付失败!"); } } catch (WxPayException e) { e.printStackTrace(); return WxPayNotifyResponse.fail(e.getMessage()); } String orderSn = result.getOutTradeNo(); String payId = result.getTransactionId(); // 分转化成元 String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee()); MallOrder order = orderService.findBySn(orderSn); if (order == null) { return WxPayNotifyResponse.fail("订单不存在 sn=" + orderSn); } // 检查这个订单是否已经处理过 if (OrderUtil.hasPayed(order)) { return WxPayNotifyResponse.success("订单已经处理成功!"); } // 检查支付订单金额 if (!totalFee.equals(order.getActualPrice().toString())) { return WxPayNotifyResponse.fail(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee); } order.setPayId(payId); order.setPayTime(new Date()); order.setOrderStatus(OrderUtil.STATUS_PAY.longValue()); order.setUpdateTime(new Date()); orderService.updateById(order); //对应预约时间数量减1 // final TjReservation byId = reservationService.getById(order.getReservationId()); // final Date reservationTime = byId.getReservationTime(); // LambdaQueryWrapper wq=new LambdaQueryWrapper<>(); // wq.eq(MallTimeConfig::getTime,reservationTime); // final MallTimeConfig one = mallTimeConfigService.getOne(wq); // one.setNowNum(one.getNowNum()-1); // mallTimeConfigService.updateById(one); //发订单信息给wx订阅服务消息————————————————start———————————————————————————————————————— Map res = new HashMap<>(); res.put("touser",UserHoder.getWxuser().getOpenid()); res.put("template_id","Gzc2BgzSsEY9uki6FThNQRLD1_An6uqpSve3PaU58PQ"); res.put("page","pages/mine/index"); res.put("miniprogram_state","formal"); //订阅消息参数值 JSONObject data = new JSONObject(); JSONObject amount3 = new JSONObject(); amount3.put("value", order.getOrderSn()); data.put("character_string2", amount3); JSONObject time4 = new JSONObject(); String dateFormat = DateUtil.format(order.getCreateTime(), "yyyy-MM-dd HH:mm:ss"); time4.put("value", dateFormat); data.put("time1", time4); final TjPackage byId = packageService.getById(order.getPacId()); if (byId!=null){ JSONObject thing5 = new JSONObject(); thing5.put("value",byId.getPacName()); data.put("thing3", thing5); }else { JSONObject thing5 = new JSONObject(); thing5.put("value","体检项目"); data.put("thing3", thing5); } JSONObject name1 = new JSONObject(); name1.put("value",order.getActualPrice()+"元"); data.put("amount4", name1); if (order.getPayId()!=null){ JSONObject thing6 = new JSONObject(); thing6.put("value", "已付款"); data.put("phrase8", thing6); }else { JSONObject thing6 = new JSONObject(); thing6.put("value", "未付款"); data.put("phrase8", thing6); } WxUtil.sendCommonSubscribeMessage(res,data); //发订单信息给wx订阅服务消息————————————————end———————————————————————————————————————— return AjaxResult.success(); } /** * 订单申请退款 * * @param body 订单信息,{ orderId:xxx } * @return 订单退款操作结果 */ @Transactional @PostMapping("/refund") @ApiOperation("订单申请退款接口") public Object refund(@RequestBody String body) { Wxuser wxuser = UserHoder.getWxuser(); if (null == wxuser) { return AjaxResult.error(); } Integer orderId = JacksonUtil.parseInteger(body, "orderId"); if (orderId == null) { return AjaxResult.error(); } LambdaQueryWrapper wq = new LambdaQueryWrapper<>(); wq.eq(MallOrder::getId, orderId); MallOrder order = orderService.getOne(wq); if (order == null) { return AjaxResult.error(); } OrderHandleOption handleOption = OrderUtil.build(order); if (!handleOption.isRefund()) { return AjaxResult.error("订单不能退款"); } // 设置订单申请退款状态 order.setOrderStatus(OrderUtil.STATUS_REFUND.longValue()); orderService.updateById(order); return AjaxResult.success(); } /** * 订单同意退款 * @param orderRefund 订单信息,{ orderId:xxx } * @return 订单退款操作结果 */ @PostMapping("/agreeToRefund") @ApiOperation(value = "订单同意退款(小程序端调用的接口)") @Transactional public AjaxResult agreeToRefund(@RequestBody OrderRefund orderRefund) { Wxuser wxuser = UserHoder.getWxuser(); if (null == wxuser) { return AjaxResult.error(); } MallOrder order = orderService.getById(orderRefund.getId()); if(null==order){ return AjaxResult.error("订单数据不存在!!!"); } if (!OrderConstants.isRefundStatus(order)&&!OrderConstants.isRefundVerify(order)) { return AjaxResult.error( "退款申请状态下订单才可以审核退款"); } BeanUtil.copyProperties(orderRefund,order); Date now = new Date(); order.setOrderStatus(Long.valueOf(OrderConstants.STATUS_REFUND_CONFIRM)); order.setUpdateTime(now); order.setRefundTime(now); order.setCloseTime(now); // 返还优惠券 // List couponUsers = couponUserService.findByOid(orderId); // for (MallCouponUser couponUser: couponUsers) { // // 优惠券状态设置为可使用 // couponUser.setStatus(CouponUserConstant.STATUS_USABLE); // couponUser.setUpdateTime(LocalDateTime.now()); // couponUserService.update(couponUser); // } if (1 == orderRefund.getRefundType()) { //原路退回的话要调用支付商接口 // 微信退款 WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest(); wxPayRefundRequest.setOutTradeNo(order.getOrderSn()); wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn()); // 元转成分 Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue(); wxPayRefundRequest.setTotalFee(totalFee); wxPayRefundRequest.setRefundFee(totalFee); WxPayRefundResult wxPayRefundResult; try { wxPayRefundResult = wxPayService.refund(wxPayRefundRequest); } catch (WxPayException e) { return AjaxResult.error("订单退款失败"); } if (!"SUCCESS".equals(wxPayRefundResult.getReturnCode())) { return AjaxResult.error("订单退款失败"); } if (!"SUCCESS".equals(wxPayRefundResult.getResultCode())) { return AjaxResult.error("订单退款失败"); } } /*notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});*/ orderService.updateById(order); //对应预约时间数量减1 final TjReservation byId = reservationService.getById(order.getReservationId()); final Date reservationTime = byId.getReservationTime(); LambdaQueryWrapper wq=new LambdaQueryWrapper<>(); wq.eq(MallTimeConfig::getTime,reservationTime); final MallTimeConfig one = mallTimeConfigService.getOne(wq); one.setNowNum(one.getNowNum()+1); mallTimeConfigService.updateById(one); byId.setIsExpire(1); reservationService.updateById(byId); transitionService.deletedTbTransitionByCusId(byId.getIdCard()); return AjaxResult.success(); } /** * 删除订单 * * @param body 订单信息,{ orderId:xxx } * @return 订单操作结果 */ @Transactional @PostMapping("/delete") @ApiOperation("删除订单接口") public Object delete(@RequestBody String body) { Wxuser wxuser = UserHoder.getWxuser(); if (null == wxuser) { return AjaxResult.error(); } Integer orderId = JacksonUtil.parseInteger(body, "orderId"); if (orderId == null) { return AjaxResult.error(); } LambdaQueryWrapper wq = new LambdaQueryWrapper<>(); wq.eq(MallOrder::getId, orderId); MallOrder order = orderService.getOne(wq); if (order == null) { return AjaxResult.error(); } OrderHandleOption handleOption = OrderUtil.build(order); if (!handleOption.isDelete()) { return AjaxResult.error("订单不能删除"); } orderService.removeById(orderId); // 删除订单详情 orderGoodsService.remove(new LambdaQueryWrapper() .eq(MallOrderGoods::getOrderId,order.getId()) ); // 售后也同时删除 LambdaQueryWrapper wq1 = new LambdaQueryWrapper<>(); wq1.eq(MallAftersale::getOrderId, order); mallAftersaleService.remove(wq1); TjReservation byId = reservationService.getById(order.getReservationId()); byId.setIsExpire(1); reservationService.updateById(byId); return AjaxResult.success(); } }