From 4a0ccb687742cbc977e5ba44330b3a8b37cf8555 Mon Sep 17 00:00:00 2001 From: renfan <2206580733@qq.com> Date: Sat, 25 Jan 2025 16:44:00 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90admin&from=E3=80=91=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=201=E3=80=81=E5=B8=88=E5=82=85=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=9B=BE=E7=89=87=202=E3=80=81=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=B8=88=E5=82=85=E9=BB=98=E8=AE=A4=E5=A4=B4=E5=83=8F?= =?UTF-8?q?=E4=B8=8D=E6=98=BE=E7=A4=BAbug=203=E3=80=81=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8F=AA=E8=8E=B7=E5=8F=96=E6=9C=8D=E5=8A=A1=E5=8C=BA=E5=9F=9F?= =?UTF-8?q?=E5=86=85=E7=9A=84=E5=B8=88=E5=82=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/distributor/DistributorCrontab.java | 78 ++-- .../crontab/impl/staff/StaffCrontab.java | 46 +-- .../service/order/impl/OrderServiceImpl.java | 35 +- .../staff/impl/StaffApplyForServiceImpl.java | 2 +- .../StaffPhysicalExaminationServiceImpl.java | 4 +- .../service/staff/impl/StaffServiceImpl.java | 98 ++--- .../service/user/impl/UserServiceImpl.java | 8 +- .../hcy/admin/validate/staff/StaffParam.java | 2 + .../com/hcy/admin/vo/order/OrderDetailVo.java | 3 + .../com/hcy/admin/vo/staff/StaffListVo.java | 2 + .../hcy/admin/vo/staff/StaffPageParam.java | 4 + admin/src/main/resources/application.yml | 24 +- .../config/wx/CustomPublicKeyVerifier.java | 37 ++ .../config/wx/CustomX509Certificate.java | 147 +++++++ .../com/hcy/common/config/wx/PemUtil.java | 262 ++++++++++++ .../common/config/wx/WxPayCustomConfig.java | 385 ++++++++++++++++++ .../com/hcy/common/dto/staff/StaffDto.java | 4 + .../com/hcy/common/entity/order/Order.java | 1 + .../com/hcy/common/entity/staff/Staff.java | 13 +- .../mapper/category/GoodsCategoryMapper.java | 2 - .../src/main/resources/mapper/OrderMapper.xml | 93 +++-- .../src/main/resources/mapper/StaffMapper.xml | 6 + .../config/wxpay/WxPayConfiguration.java | 13 +- .../hcy/front/controller/OrderController.java | 19 + .../front/service/order/IOrderService.java | 8 + .../service/order/impl/OrderServiceImpl.java | 157 ++++++- .../impl/StaffReceiveOrderServiceImpl.java | 74 ++-- .../service/staff/impl/StaffServiceImpl.java | 63 ++- .../hcy/front/validate/order/OrderParam.java | 4 + .../com/hcy/front/vo/order/OrderDetailVo.java | 4 + .../com/hcy/front/vo/order/OrderListVo.java | 2 + front/src/main/resources/application.yml | 20 +- 32 files changed, 1319 insertions(+), 301 deletions(-) create mode 100644 common/src/main/java/com/hcy/common/config/wx/CustomPublicKeyVerifier.java create mode 100644 common/src/main/java/com/hcy/common/config/wx/CustomX509Certificate.java create mode 100644 common/src/main/java/com/hcy/common/config/wx/PemUtil.java create mode 100644 common/src/main/java/com/hcy/common/config/wx/WxPayCustomConfig.java diff --git a/admin/src/main/java/com/hcy/admin/service/crontab/impl/distributor/DistributorCrontab.java b/admin/src/main/java/com/hcy/admin/service/crontab/impl/distributor/DistributorCrontab.java index 2f96e16..eff3f2e 100644 --- a/admin/src/main/java/com/hcy/admin/service/crontab/impl/distributor/DistributorCrontab.java +++ b/admin/src/main/java/com/hcy/admin/service/crontab/impl/distributor/DistributorCrontab.java @@ -69,43 +69,43 @@ public class DistributorCrontab { } } - @Transactional - public void checkDistributorWithdraw(){ - List distributorWithdraws = distributorWithdrawMapper.selectList(new LambdaQueryWrapper() - .eq(WithdrawCommission::getStatus, DistributorWithdrawStatusEnum.WITHDRAW.getStatus())); - if(distributorWithdraws.isEmpty()){ - return; - } - log.info("处理佣金提现结果"); - MerchantTransferService merchantTransferService = WxPayServiceUtils.wxPayService(PayChannelEnum.MP_CHANNEL.getCode()).getMerchantTransferService(); - for (WithdrawCommission item : distributorWithdraws) { - MerchantDetailsQueryRequest merchantDetailsQueryRequest = new MerchantDetailsQueryRequest(); - merchantDetailsQueryRequest.setOutBatchNo(item.getSn()); - merchantDetailsQueryRequest.setOutDetailNo(item.getDetailSn()); - try { - DetailsQueryResult detailsQueryResult = merchantTransferService.queryMerchantDetails(merchantDetailsQueryRequest); - if(DistributorWithdrawResultEnum.FAIL.getStatus().equals(detailsQueryResult.getDetailStatus())){ - //判断当前提现记录是分销商还师傅的 - if(item.getDistributorId() != null){ - Distributor distributor = distributorMapper.queryDistributorById(item.getDistributorId()); - distributor.setCanWithdrawCommission(distributor.getCanWithdrawCommission().add(item.getWithdrawMoney())); - distributorMapper.updateById(distributor); - }else{ - Staff staff = staffMapper.findStaffById(item.getStaffId()); - staff.setCanWithdrawCommission(staff.getCanWithdrawCommission().add(item.getWithdrawMoney())); - staffMapper.updateById(staff); - } - item.setStatus(DistributorWithdrawStatusEnum.WITHDRAW_FAIL.getStatus()); - item.setFailReason(detailsQueryResult.getFailReason()); - distributorWithdrawMapper.updateById(item); - }else{ - item.setUpdateTime(TimeUtil.parseStrToDate(detailsQueryResult.getUpdateTime())); - item.setStatus(DistributorWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()); - distributorWithdrawMapper.updateById(item); - } - }catch (WxPayException e){ - log.info(e.getErrCodeDes()); - } - } - } +// @Transactional +// public void checkDistributorWithdraw(){ +// List distributorWithdraws = distributorWithdrawMapper.selectList(new LambdaQueryWrapper() +// .eq(WithdrawCommission::getStatus, DistributorWithdrawStatusEnum.WITHDRAW.getStatus())); +// if(distributorWithdraws.isEmpty()){ +// return; +// } +// log.info("处理佣金提现结果"); +// MerchantTransferService merchantTransferService = WxPayServiceUtils.wxPayService(PayChannelEnum.MP_CHANNEL.getCode()).getMerchantTransferService(); +// for (WithdrawCommission item : distributorWithdraws) { +// MerchantDetailsQueryRequest merchantDetailsQueryRequest = new MerchantDetailsQueryRequest(); +// merchantDetailsQueryRequest.setOutBatchNo(item.getSn()); +// merchantDetailsQueryRequest.setOutDetailNo(item.getDetailSn()); +// try { +// DetailsQueryResult detailsQueryResult = merchantTransferService.queryMerchantDetails(merchantDetailsQueryRequest); +// if(DistributorWithdrawResultEnum.FAIL.getStatus().equals(detailsQueryResult.getDetailStatus())){ +// //判断当前提现记录是分销商还师傅的 +// if(item.getDistributorId() != null){ +// Distributor distributor = distributorMapper.queryDistributorById(item.getDistributorId()); +// distributor.setCanWithdrawCommission(distributor.getCanWithdrawCommission().add(item.getWithdrawMoney())); +// distributorMapper.updateById(distributor); +// }else{ +// Staff staff = staffMapper.findStaffById(item.getStaffId()); +// staff.setCanWithdrawCommission(staff.getCanWithdrawCommission().add(item.getWithdrawMoney())); +// staffMapper.updateById(staff); +// } +// item.setStatus(DistributorWithdrawStatusEnum.WITHDRAW_FAIL.getStatus()); +// item.setFailReason(detailsQueryResult.getFailReason()); +// distributorWithdrawMapper.updateById(item); +// }else{ +// item.setUpdateTime(TimeUtil.parseStrToDate(detailsQueryResult.getUpdateTime())); +// item.setStatus(DistributorWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()); +// distributorWithdrawMapper.updateById(item); +// } +// }catch (WxPayException e){ +// log.info(e.getErrCodeDes()); +// } +// } +// } } diff --git a/admin/src/main/java/com/hcy/admin/service/crontab/impl/staff/StaffCrontab.java b/admin/src/main/java/com/hcy/admin/service/crontab/impl/staff/StaffCrontab.java index 9b5f55b..23aa1b9 100644 --- a/admin/src/main/java/com/hcy/admin/service/crontab/impl/staff/StaffCrontab.java +++ b/admin/src/main/java/com/hcy/admin/service/crontab/impl/staff/StaffCrontab.java @@ -87,29 +87,29 @@ public class StaffCrontab { /** * 解冻师傅佣金 */ - @Transactional - public void unfreezingCommission(){ - log.info("解冻师傅佣金"); - //获取所有待解冻的佣金 - QueryWrapper staffCommissionQueryWrapper = new QueryWrapper<>(); - staffCommissionQueryWrapper.eq("is_delete", GlobalConstant.NOT_DELETE); - staffCommissionQueryWrapper.eq("status", StaffCommissionStatusEnum.FREEZE.getCode()); - List staffCommissions = staffCommissionMapper.selectList(staffCommissionQueryWrapper); - - for (StaffCommission item : staffCommissions) { - QueryWrapper staffQueryWrapper = new QueryWrapper<>(); - staffQueryWrapper.eq("id",item.getStaffId()); - Staff staff = staffMapper.selectOne(staffQueryWrapper); - if(staff != null){ - //解冻佣金相加 - staff.setCanWithdrawCommission(staff.getCanWithdrawCommission().add(item.getCommission())); - staffMapper.updateById(staff); - //修改解冻状态为已解冻 - item.setStatus(DistributorCommissionStatusEnum.MAY_WITHDRAW.getCode()); - staffCommissionMapper.updateById(item); - } - } - } +// @Transactional +// public void unfreezingCommission(){ +// log.info("解冻师傅佣金"); +// //获取所有待解冻的佣金 +// QueryWrapper staffCommissionQueryWrapper = new QueryWrapper<>(); +// staffCommissionQueryWrapper.eq("is_delete", GlobalConstant.NOT_DELETE); +// staffCommissionQueryWrapper.eq("status", StaffCommissionStatusEnum.FREEZE.getCode()); +// List staffCommissions = staffCommissionMapper.selectList(staffCommissionQueryWrapper); +// +// for (StaffCommission item : staffCommissions) { +// QueryWrapper staffQueryWrapper = new QueryWrapper<>(); +// staffQueryWrapper.eq("id",item.getStaffId()); +// Staff staff = staffMapper.selectOne(staffQueryWrapper); +// if(staff != null){ +// //解冻佣金相加 +// staff.setCanWithdrawCommission(staff.getCanWithdrawCommission().add(item.getCommission())); +// staffMapper.updateById(staff); +// //修改解冻状态为已解冻 +// item.setStatus(DistributorCommissionStatusEnum.MAY_WITHDRAW.getCode()); +// staffCommissionMapper.updateById(item); +// } +// } +// } } diff --git a/admin/src/main/java/com/hcy/admin/service/order/impl/OrderServiceImpl.java b/admin/src/main/java/com/hcy/admin/service/order/impl/OrderServiceImpl.java index 7d1cf8a..a628982 100644 --- a/admin/src/main/java/com/hcy/admin/service/order/impl/OrderServiceImpl.java +++ b/admin/src/main/java/com/hcy/admin/service/order/impl/OrderServiceImpl.java @@ -335,6 +335,9 @@ public class OrderServiceImpl extends ServiceImpl implements vo.setPayTime(TimeUtil.timestampToDate(model.getPayTime())); vo.setFinishTime(TimeUtil.timestampToDate(model.getFinishTime())); vo.setCancelTime(TimeUtil.timestampToDate(model.getCancelTime())); + if(model.getServeImg() != null){ + vo.setServiceImages(Arrays.asList(model.getServeImg().split(","))); //将数组转成列表返回给前端 + } // 用户昵称 UserVo userVo = userService.detail(model.getUserId().intValue()); vo.setNickname(userVo.getNickname()); @@ -356,6 +359,17 @@ public class OrderServiceImpl extends ServiceImpl implements } } + // 师傅信息 + if(model.getStaffId() != null){ + Staff staff = staffMapper.findStaffById(model.getStaffId()); + if(staff != null){ + vo.setStaffId(staff.getId()); + vo.setStaffName(staff.getName()); + vo.setStaffImage(staff.getHeadPortrait()); + vo.setStaffSn(staff.getSn()); + } + } + //展示历史指派记录 List staffReassignments = staffReassignmentMapper.selectList(new LambdaQueryWrapper() .eq(StaffReassignment::getOrderId, orderId) @@ -384,6 +398,13 @@ public class OrderServiceImpl extends ServiceImpl implements vo.setDistributorContact(userVo.getDistContact()); vo.setDistributorGroup(userVo.getDistGroup()); + //退款信息 + OrderRefund orderRefund = orderRefundMapper.findOrderRefundByOrderId(orderId); + if(orderRefund != null){ + OrderRefundDetailVo orderRefundDetailVo = new OrderRefundDetailVo();//退款记录 + orderRefundDetailVo.setRefundReason(orderRefund.getRefundReason()); //退款原因 + vo.setOrderRefundDetailVo(orderRefundDetailVo); + } return vo; } @@ -639,7 +660,7 @@ public class OrderServiceImpl extends ServiceImpl implements new QueryWrapper() .eq("id", staffId) .last("limit 1")); - if(staff != null && staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode()) { + if(staff != null ) { if(staff.getIsReceiveOrder() == StaffStatusEnum.ORDER_NOT_AVAILABLE.getCode()){ throw new OperateException("当前师傅处于不可接单状态"); }else if(staff.getIsOrder() == StaffStatusEnum.REST.getCode()){ @@ -688,14 +709,6 @@ public class OrderServiceImpl extends ServiceImpl implements deductScore = new BigDecimal("0"); timeBefore = Math.toIntExact(TimeUtil.nowTimeDifferenceMinute(model.getAppointTimeStart())); } - //要被指派的师傅不是运营师傅就扣分 - if (staff != null && staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode()) { - Staff beforeStaff = staffMapper.findStaffById(model.getStaffId()); - //扣除申请改派师傅的分数 - beforeStaff.setAddScore(BigDecimal.valueOf(beforeStaff.getAddScore()).subtract(deductScore).doubleValue()); - staffMapper.updateById(beforeStaff); - } - //修改指派记录 StaffReassignment staffReassignment = staffReassignmentMapper.selectOne(new LambdaQueryWrapper() .eq(StaffReassignment::getIsDelete,GlobalConstant.NOT_DELETE) @@ -889,7 +902,7 @@ public class OrderServiceImpl extends ServiceImpl implements if ("SUCCESS".equals(tradeState)) { // 修改订单的支付信息 model.setPayTime(TimeUtil.dateToTimestamp(TimeUtil.getStringByRFC3339(queryOrderV3.getSuccessTime()))); - model.setOrderStatus(OrderStatusEnum.RESERVE.getStatus()); + model.setOrderStatus(OrderStatusEnum.SERVICING.getStatus()); model.setPayStatus(OrderPayStatusEnum.PAY.getStatus()); model.setPayWay(OrderPlayTypeEnum.WECHAT_PAY.getType()); model.setTransactionId(queryOrderV3.getTransactionId()); @@ -969,7 +982,7 @@ public class OrderServiceImpl extends ServiceImpl implements throw new OperateException("只有预约中的服务,师傅才可以确认服务"); } - Staff staff = staffMapper.findStaffById(orderParam.getStaffId()); + Staff staff = staffMapper.findStaffById(model.getStaffId()); if (staff == null) { throw new OperateException("师傅不存在"); } diff --git a/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffApplyForServiceImpl.java b/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffApplyForServiceImpl.java index e554c88..5ef1e8b 100644 --- a/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffApplyForServiceImpl.java +++ b/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffApplyForServiceImpl.java @@ -211,7 +211,7 @@ public class StaffApplyForServiceImpl implements IStaffApplyForService { BeanUtils.copyProperties(model,staff); //实名认证 staff.setId(null); - staff.setIsAuthentication(StaffStatusEnum.AUTHENTICATION.getCode()); +// staff.setIsAuthentication(StaffStatusEnum.AUTHENTICATION.getCode()); staff.setCreateTime(TimeUtil.nowDate()); staff.setSn(staffService.generateNum()); staffMapper.insert(staff); diff --git a/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffPhysicalExaminationServiceImpl.java b/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffPhysicalExaminationServiceImpl.java index 08919ff..140911c 100644 --- a/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffPhysicalExaminationServiceImpl.java +++ b/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffPhysicalExaminationServiceImpl.java @@ -128,7 +128,7 @@ public class StaffPhysicalExaminationServiceImpl implements IStaffPhysicalExamin .eq("is_delete", GlobalConstant.NOT_DELETE) .eq("id", model.getStaffId())); //实名认证 - staff.setPhysicalExamination(model.getPhysicalExamination()); +// staff.setPhysicalExamination(model.getPhysicalExamination()); staff.setUpdateTime(TimeUtil.nowDate()); staffMapper.updateById(staff); }else{ @@ -160,7 +160,7 @@ public class StaffPhysicalExaminationServiceImpl implements IStaffPhysicalExamin } } - staff.setPhysicalExamination(physicalExamination.toString()); +// staff.setPhysicalExamination(physicalExamination.toString()); staffMapper.updateById(staff); } } diff --git a/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffServiceImpl.java b/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffServiceImpl.java index 58cab08..62f6ec8 100644 --- a/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffServiceImpl.java +++ b/admin/src/main/java/com/hcy/admin/service/staff/impl/StaffServiceImpl.java @@ -21,10 +21,12 @@ import com.hcy.common.dto.result.StaffResultDto; import com.hcy.common.dto.staff.StaffDto; import com.hcy.common.entity.category.GoodsCategory; import com.hcy.common.entity.comment.GoodsComment; +import com.hcy.common.entity.goods.Goods; import com.hcy.common.entity.staff.Staff; import com.hcy.common.entity.staff.StaffApplyFor; import com.hcy.common.entity.staff.StaffCommission; import com.hcy.common.entity.staff.StaffPhysicalExamination; +import com.hcy.common.entity.user.User; import com.hcy.common.enums.RecommendEnum; import com.hcy.common.enums.StatusEnum; import com.hcy.common.enums.staff.StaffApplyForStatusEnum; @@ -37,10 +39,8 @@ import com.hcy.common.mapper.staff.StaffApplyForMapper; import com.hcy.common.mapper.staff.StaffCommissionMapper; import com.hcy.common.mapper.staff.StaffMapper; import com.hcy.common.mapper.staff.StaffPhysicalExaminationMapper; -import com.hcy.common.utils.RegularExpressionUtil; -import com.hcy.common.utils.StringUtil; -import com.hcy.common.utils.TimeUtil; -import com.hcy.common.utils.UrlUtil; +import com.hcy.common.mapper.user.UserMapper; +import com.hcy.common.utils.*; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; @@ -88,6 +88,9 @@ public class StaffServiceImpl extends ServiceImpl implements @Resource GoodsCategoryMapper goodsCategoryMapper; + @Resource + private UserMapper userMapper; + /** * 师傅列表 * @@ -99,6 +102,15 @@ public class StaffServiceImpl extends ServiceImpl implements Page page = new Page<>(params.getPageNo(), params.getPageSize()); StaffDto pageDto = new StaffDto(); BeanUtils.copyProperties(params, pageDto); + + //服务id不为空时 查询对应服务分类师傅 + if(params.getGoodsId() != null){ + Goods goods = goodsService.getById(params.getGoodsId()); + if(goods != null){ + pageDto.setGoodsCategoryId(goods.getCategoryId()); + } + } + if(pageDto.getAppointTimeStart() != null && pageDto.getAppointTimeEnd() != null){ long time = 60 * 60; //指派师傅时查询服务时间前后一个小时是否有交叉的订单 @@ -116,15 +128,17 @@ public class StaffServiceImpl extends ServiceImpl implements for (StaffResultDto item : resultDtoPage.getRecords()) { StaffListVo vo = new StaffListVo(); BeanUtils.copyProperties(item, vo); - vo.setStatusName(statusMap.get(vo.getStatus())); vo.setIsRecommendName(recommendMap.get(vo.getIsRecommend())); vo.setProvince(regionMap.get(vo.getProvinceId())); vo.setCity(regionMap.get(vo.getCityId())); vo.setDistrict(regionMap.get(vo.getDistrictId())); vo.setAvatarUrl(UrlUtil.toAbsoluteUrl(item.getAvatarUri())); - vo.setPhysicalExamination(item.getPhysicalExamination()); - //获取待结算金额 - vo.setToBeSettledMoney(getToBeSettledMoney(item.getId())); +// if (!item.getAvatarUri().equals("") && !item.getAvatarUri().equals("/api/static/default_avatar.png")) { +// vo.setAvatarUrl(UrlUtil.toAbsoluteUrl(item.getAvatarUri())); +// } else { +// String avatar = ConfigUtil.get("user", "defaultAvatar", "/api/static/default_avatar.png"); +// vo.setAvatarUrl(UrlUtil.toAbsoluteUrl(avatar)); +// } list.add(vo); } return PageResult.iPageHandle(resultDtoPage.getTotal(), resultDtoPage.getCurrent(), resultDtoPage.getSize(), list); @@ -187,43 +201,24 @@ public class StaffServiceImpl extends ServiceImpl implements public void add(StaffParam staffParam) { Assert.notNull(staffParam.getUserId(),"请选择绑定的用户"); - //校验数据完整性 - if(!RegularExpressionUtil.checkIdCard(staffParam.getIdCard())){ - throw new OperateException("身份证格式错误"); - }else if(!RegularExpressionUtil.checkPhone(staffParam.getMobile())){ + if(!RegularExpressionUtil.checkPhone(staffParam.getMobile())){ throw new OperateException("无效手机号码"); } + User user = userMapper.selectOne( + new QueryWrapper() + .eq("id", staffParam.getUserId()) + .eq("is_delete", 0) + .last("limit 1")); + Assert.notNull(user, "当前用户不存在!"); //新增师傅 Staff staff = new Staff(); BeanUtils.copyProperties(staffParam,staff); - staff.setHeadPortrait(staffParam.getFiles().getAvatar().get(0)); - staff.setIdCardImg(staffParam.getFiles().getPortrait().get(0) + "," + staffParam.getFiles().getBackend().get(0)); - StringBuilder physicalExamination = new StringBuilder(); - if(!staffParam.getFiles().getPdf().isEmpty()){ - physicalExamination.append(staffParam.getFiles().getPdf().get(0)); - } - if(staffParam.getFiles().getReport() != null){ - for (String img : staffParam.getFiles().getReport()) { - if(StringUtil.isNotEmpty(physicalExamination.toString())){ - physicalExamination.append(",").append(img); - }else{ - physicalExamination.append(img); - } - } - } - - staff.setIsAuthentication(StaffStatusEnum.AUTHENTICATION.getCode()); + staff.setHeadPortrait(UrlUtil.toAbsoluteUrl(user.getAvatar())); staff.setCreateTime(TimeUtil.nowDate()); staff.setSn(generateNum()); - staff.setPhysicalExamination(physicalExamination.toString()); staff.setCreateTime(TimeUtil.nowDate()); - staff.setStatus(StaffApplyForStatusEnum.IN_THE_APPLICATION.getCode()); - if(staff.getIsOperational() != null){ - staff.setIsOperational(staffParam.getIsOperational()); - staff.setWorkStartTime(staffParam.getWorkStartTime()); - staff.setWorkEndTime(staffParam.getWorkEndTime()); - } + staffMapper.insert(staff); } @@ -279,9 +274,6 @@ public class StaffServiceImpl extends ServiceImpl implements model.setIsRecommend(staffParam.getIsRecommend()); model.setUpdateTime(TimeUtil.nowDate()); model.setIsReceiveOrder(staffParam.getIsReceiveOrder()); - model.setIsOperational(staffParam.getIsOperational()); - model.setWorkStartTime(staffParam.getWorkStartTime()); - model.setWorkEndTime(staffParam.getWorkEndTime()); staffMapper.updateById(model); } @@ -299,19 +291,9 @@ public class StaffServiceImpl extends ServiceImpl implements .last("limit 1")); Assert.notNull(model, "师傅不存在!"); - BigDecimal zero = new BigDecimal("0"); Boolean result = orderService.existOrderByStaffId(model.getId()); if (result) { throw new OperateException("该师傅还有未完成的订单,不能删除!"); - }else if(model.getCanWithdrawCommission().compareTo(zero) > 0){ - throw new OperateException("该师傅可提现佣金大于0,不能删除!"); - } - BigDecimal sum = staffCommissionMapper.sum("commission", new QueryWrapper() - .eq("is_delete", GlobalConstant.NOT_DELETE) - .eq("staff_id", model.getId()) - .eq("status", StaffCommissionStatusEnum.FREEZE.getCode())); - if(sum.compareTo(zero) > 0){ - throw new OperateException("该师傅待结算佣金大于0,不能删除!"); } model.setIsDelete(GlobalConstant.DELETE); model.setDeleteTime(TimeUtil.nowDate()); @@ -442,15 +424,15 @@ public class StaffServiceImpl extends ServiceImpl implements public void updateStaffOperationalStatus(StaffParam staffParam) { Staff staff = super.getById(staffParam.getId()); Assert.notNull(staff, "师傅不存在!"); - - if(staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode() && - (StringUtil.isEmpty(staff.getWorkStartTime()) || StringUtil.isEmpty(staff.getWorkEndTime()))){ - throw new OperateException("请先设置该运营师傅的工作时间"); - } - - staff.setIsOperational(staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode() ? - StaffStatusEnum.OPERATIONAL_STAFF.getCode() : - StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode()); +// +// if(staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode() && +// (StringUtil.isEmpty(staff.getWorkStartTime()) || StringUtil.isEmpty(staff.getWorkEndTime()))){ +// throw new OperateException("请先设置该运营师傅的工作时间"); +// } +// +// staff.setIsOperational(staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode() ? +// StaffStatusEnum.OPERATIONAL_STAFF.getCode() : +// StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode()); super.updateById(staff); } diff --git a/admin/src/main/java/com/hcy/admin/service/user/impl/UserServiceImpl.java b/admin/src/main/java/com/hcy/admin/service/user/impl/UserServiceImpl.java index 3ada42f..95f8006 100644 --- a/admin/src/main/java/com/hcy/admin/service/user/impl/UserServiceImpl.java +++ b/admin/src/main/java/com/hcy/admin/service/user/impl/UserServiceImpl.java @@ -410,7 +410,13 @@ public class UserServiceImpl implements IUserService { UserVo userVo = new UserVo(); BeanUtils.copyProperties(item,userVo); userVo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime())); - userVo.setAvatar(UrlUtil.toAbsoluteUrl(item.getAvatar())); +// userVo.setAvatar(UrlUtil.toAbsoluteUrl(item.getAvatar())); + if (!item.getAvatar().equals("") && !item.getAvatar().equals("/api/static/default_avatar.png")) { + userVo.setAvatar(UrlUtil.toAbsoluteUrl(item.getAvatar())); + } else { + String avatar = ConfigUtil.get("user", "defaultAvatar", "/api/static/default_avatar.png"); + userVo.setAvatar(UrlUtil.toAbsoluteUrl(avatar)); + } userVoList.add(userVo); } diff --git a/admin/src/main/java/com/hcy/admin/validate/staff/StaffParam.java b/admin/src/main/java/com/hcy/admin/validate/staff/StaffParam.java index 85a1e4d..015d978 100644 --- a/admin/src/main/java/com/hcy/admin/validate/staff/StaffParam.java +++ b/admin/src/main/java/com/hcy/admin/validate/staff/StaffParam.java @@ -125,4 +125,6 @@ public class StaffParam implements Serializable { private StaffUploadFile files; private String code; //验证码 + private String avatarUri;// 用户头像 + } diff --git a/admin/src/main/java/com/hcy/admin/vo/order/OrderDetailVo.java b/admin/src/main/java/com/hcy/admin/vo/order/OrderDetailVo.java index ea7cff7..abcbce2 100644 --- a/admin/src/main/java/com/hcy/admin/vo/order/OrderDetailVo.java +++ b/admin/src/main/java/com/hcy/admin/vo/order/OrderDetailVo.java @@ -172,4 +172,7 @@ public class OrderDetailVo implements Serializable { private String distributorContact; @ApiModelProperty(value = "分销员组别") private String distributorGroup; + + private List serviceImages; //服务图片 + } diff --git a/admin/src/main/java/com/hcy/admin/vo/staff/StaffListVo.java b/admin/src/main/java/com/hcy/admin/vo/staff/StaffListVo.java index a57609a..36f1efb 100644 --- a/admin/src/main/java/com/hcy/admin/vo/staff/StaffListVo.java +++ b/admin/src/main/java/com/hcy/admin/vo/staff/StaffListVo.java @@ -83,4 +83,6 @@ public class StaffListVo implements Serializable { private Integer isOperational; //是否运营师傅:0-不是 1-是 private String workStartTime; //工作开始时间 private String workEndTime; //工作结束时间 + + private int uploadServiceImgBtn; //上传服务图片按钮:0-隐藏;1-显示 } diff --git a/admin/src/main/java/com/hcy/admin/vo/staff/StaffPageParam.java b/admin/src/main/java/com/hcy/admin/vo/staff/StaffPageParam.java index d472cfc..422b1d6 100644 --- a/admin/src/main/java/com/hcy/admin/vo/staff/StaffPageParam.java +++ b/admin/src/main/java/com/hcy/admin/vo/staff/StaffPageParam.java @@ -35,4 +35,8 @@ public class StaffPageParam extends PageParam { private Integer isReceiveOrder; //是否可以接单:0-可以;1-不可接单; private Integer isOrder; //师傅是否接单:0-接单中;1-休息中; + private Long goodsId; //服务id + + private Long staffId; //师傅id + } diff --git a/admin/src/main/resources/application.yml b/admin/src/main/resources/application.yml index 6e1e171..acd24a4 100644 --- a/admin/src/main/resources/application.yml +++ b/admin/src/main/resources/application.yml @@ -1,7 +1,7 @@ # 项目配置 like: -# upload-directory: /data/file/uploads/ # 文件上传目录 - upload-directory: E:\img\ + upload-directory: /data/file/uploads/ # 文件上传目录 +# upload-directory: E:\img\ # 服务配置 server: @@ -24,16 +24,16 @@ spring: static-path-pattern: /api/static/** # 数据源配置 datasource: - url: jdbc:mysql://192.168.111.98:3306/homemaking_no_staff?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false - type: com.zaxxer.hikari.HikariDataSource # 数据源类型 - driver-class-name: com.mysql.jdbc.Driver # MySql的驱动 - username: root # 数据库账号 - password: 1234 -# url: jdbc:mysql://123.207.77.26:3306/homemaking?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false +# url: jdbc:mysql://192.168.111.98:3306/homemaking_no_staff?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false # type: com.zaxxer.hikari.HikariDataSource # 数据源类型 # driver-class-name: com.mysql.jdbc.Driver # MySql的驱动 -# username: Homemaking # 数据库账号 -# password: kpHaxTyz4ehkYDpS +# username: root # 数据库账号 +# password: 1234 + url: jdbc:mysql://123.207.77.26:3306/homemaking?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false + type: com.zaxxer.hikari.HikariDataSource # 数据源类型 + driver-class-name: com.mysql.jdbc.Driver # MySql的驱动 + username: Homemaking # 数据库账号 + password: kpHaxTyz4ehkYDpS hikari: connection-timeout: 30000 # 等待连接分配连接的最大时长(毫秒),超出时长还没可用连接则发送SQLException,默认30秒 @@ -74,5 +74,5 @@ mybatis-plus: table-prefix: la_ # 设置表前缀 configuration-properties: prefix: la_ # 自定义表前缀标签${prefix} -# configuration: #打印sql日志 -# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl \ No newline at end of file + configuration: #打印sql日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl \ No newline at end of file diff --git a/common/src/main/java/com/hcy/common/config/wx/CustomPublicKeyVerifier.java b/common/src/main/java/com/hcy/common/config/wx/CustomPublicKeyVerifier.java new file mode 100644 index 0000000..2aebc23 --- /dev/null +++ b/common/src/main/java/com/hcy/common/config/wx/CustomPublicKeyVerifier.java @@ -0,0 +1,37 @@ +package com.hcy.common.config.wx; + +import com.github.binarywang.wxpay.v3.auth.Verifier; +import me.chanjar.weixin.common.error.WxRuntimeException; + +import java.security.*; +import java.security.cert.X509Certificate; +import java.util.Base64; + +public class CustomPublicKeyVerifier implements Verifier { + private PublicKey publicKey; + private String publicKeyId; + public CustomPublicKeyVerifier(PublicKey publicKey,String publicKeyId) { + this.publicKey = publicKey; + this.publicKeyId = publicKeyId; + } + @Override + public boolean verify(String serialNumber, byte[] message, String signature) { + try { + Signature sign = Signature.getInstance("SHA256withRSA"); + sign.initVerify(publicKey); + sign.update(message); + return sign.verify(Base64.getDecoder().decode(signature)); + } catch (NoSuchAlgorithmException e) { + throw new WxRuntimeException("当前Java环境不支持SHA256withRSA", e); + } catch (SignatureException e) { + throw new WxRuntimeException("签名验证过程发生了错误", e); + } catch (InvalidKeyException e) { + throw new WxRuntimeException("无效的证书", e); + } + } + + @Override + public X509Certificate getValidCertificate() { + return new CustomX509Certificate(publicKey,publicKeyId); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/hcy/common/config/wx/CustomX509Certificate.java b/common/src/main/java/com/hcy/common/config/wx/CustomX509Certificate.java new file mode 100644 index 0000000..56a22f2 --- /dev/null +++ b/common/src/main/java/com/hcy/common/config/wx/CustomX509Certificate.java @@ -0,0 +1,147 @@ +package com.hcy.common.config.wx; + +import java.math.BigInteger; +import java.security.*; +import java.security.cert.*; +import java.util.Date; +import java.util.Set; + +public class CustomX509Certificate extends X509Certificate { + private PublicKey publicKey; + private String publicKeyId; + + public CustomX509Certificate(PublicKey publicKey, String publicKeyId) { + super(); + this.publicKey = publicKey; + this.publicKeyId = publicKeyId; + } + + @Override + public byte[] getEncoded() throws CertificateEncodingException { + return new byte[0]; + } + + @Override + public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { + + } + + @Override + public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { + + } + + @Override + public String toString() { + return null; + } + + public PublicKey getPublicKey() { + return this.publicKey; + } + + @Override + public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { + + } + + @Override + public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { + + } + + @Override + public int getVersion() { + return 0; + } + + @Override + public BigInteger getSerialNumber() { + return new BigInteger(publicKeyId.replace("PUB_KEY_ID_", ""), 16); + } + + @Override + public Principal getIssuerDN() { + return null; + } + + @Override + public Principal getSubjectDN() { + return null; + } + + @Override + public Date getNotBefore() { + return null; + } + + @Override + public Date getNotAfter() { + return null; + } + + @Override + public byte[] getTBSCertificate() throws CertificateEncodingException { + return new byte[0]; + } + + @Override + public byte[] getSignature() { + return new byte[0]; + } + + @Override + public String getSigAlgName() { + return null; + } + + @Override + public String getSigAlgOID() { + return null; + } + + @Override + public byte[] getSigAlgParams() { + return new byte[0]; + } + + @Override + public boolean[] getIssuerUniqueID() { + return new boolean[0]; + } + + @Override + public boolean[] getSubjectUniqueID() { + return new boolean[0]; + } + + @Override + public boolean[] getKeyUsage() { + return new boolean[0]; + } + + @Override + public int getBasicConstraints() { + return 0; + } + + @Override + public boolean hasUnsupportedCriticalExtension() { + return false; + } + + @Override + public Set getCriticalExtensionOIDs() { + return null; + } + + @Override + public Set getNonCriticalExtensionOIDs() { + return null; + } + + @Override + public byte[] getExtensionValue(String oid) { + return new byte[0]; + } +} \ No newline at end of file diff --git a/common/src/main/java/com/hcy/common/config/wx/PemUtil.java b/common/src/main/java/com/hcy/common/config/wx/PemUtil.java new file mode 100644 index 0000000..8406955 --- /dev/null +++ b/common/src/main/java/com/hcy/common/config/wx/PemUtil.java @@ -0,0 +1,262 @@ +package com.hcy.common.config.wx; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +/** + * PEM工具 + */ +public class PemUtil { + private static final int DEFAULT_BUFFER_SIZE = 8192; + + private PemUtil() { + } + + /** + * 从字符串中加载RSA私钥。 + * + * @param keyString 私钥字符串 + * @return RSA私钥 + */ + public static PrivateKey loadPrivateKeyFromString(String keyString) { + try { + keyString = + keyString + .replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s+", ""); + return KeyFactory.getInstance("RSA") + .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString))); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } catch (InvalidKeySpecException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从字符串中加载指定算法的私钥 + * + * @param keyString 私钥字符串 + * @param algorithm 私钥算法 + * @param provider the provider + * @return 私钥 + */ + public static PrivateKey loadPrivateKeyFromString( + String keyString, String algorithm, String provider) { + try { + keyString = + keyString + .replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s+", ""); + return KeyFactory.getInstance(algorithm, provider) + .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString))); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } catch (InvalidKeySpecException | NoSuchProviderException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从字符串中加载RSA公钥。 + * + * @param keyString 公钥字符串 + * @return RSA公钥 + */ + public static PublicKey loadPublicKeyFromString(String keyString) { + try { + keyString = + keyString + .replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replaceAll("\\s+", ""); + return KeyFactory.getInstance("RSA") + .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(keyString))); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } catch (InvalidKeySpecException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从文件路径加载RSA私钥 + * + * @param keyPath 私钥路径 + * @return RSA私钥 + */ + public static PrivateKey loadPrivateKeyFromPath(String keyPath) { + return loadPrivateKeyFromString(readKeyStringFromPath(keyPath)); + } + + /** + * 从文件路径加载指定算法的私钥 + * + * @param keyPath 私钥路径 + * @param algorithm 私钥算法 + * @param provider the provider + * @return 私钥 + */ + public static PrivateKey loadPrivateKeyFromPath( + String keyPath, String algorithm, String provider) { + return loadPrivateKeyFromString(readKeyStringFromPath(keyPath), algorithm, provider); + } + + /** + * 从文件路径加载RSA公钥 + * + * @param keyPath 公钥路径 + * @return RSA公钥 + */ + public static PublicKey loadPublicKeyFromPath(String keyPath) { + return loadPublicKeyFromString(keyPath); + } + + private static String readKeyStringFromPath(String keyPath) { + try (FileInputStream inputStream = new FileInputStream(keyPath)) { + return ioToString(inputStream); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * 从输入流加载X.509证书 + * + * @param inputStream 私钥输入流 + * @return X.509证书 + */ + public static X509Certificate loadX509FromStream(InputStream inputStream) { + try { + return (X509Certificate) + CertificateFactory.getInstance("X.509").generateCertificate(inputStream); + } catch (CertificateException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从输入流加载X.509证书 + * + * @param inputStream 私钥输入流 + * @param provider the provider + * @return X.509证书 + */ + public static X509Certificate loadX509FromStream(InputStream inputStream, String provider) { + try { + return (X509Certificate) + CertificateFactory.getInstance("X.509", provider).generateCertificate(inputStream); + } catch (CertificateException | NoSuchProviderException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从文件路径加载X.509证书 + * + * @param certificatePath 证书文件路径 + * @return X.509证书 + */ + public static X509Certificate loadX509FromPath(String certificatePath) { + try (FileInputStream inputStream = new FileInputStream(certificatePath)) { + return loadX509FromStream(inputStream); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * 从文件路径加载X.509证书 + * + * @param certificatePath 证书文件路径 + * @param provider the provider + * @return X.509证书 + */ + public static X509Certificate loadX509FromPath(String certificatePath, String provider) { + try (FileInputStream inputStream = new FileInputStream(certificatePath)) { + return loadX509FromStream(inputStream, provider); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * 从字符串加载X.509证书 + * + * @param certificateString 证书字符串 + * @return X.509证书 + */ + public static X509Certificate loadX509FromString(String certificateString) { + try (ByteArrayInputStream inputStream = + new ByteArrayInputStream(certificateString.getBytes(StandardCharsets.UTF_8))) { + return loadX509FromStream(inputStream); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * 从字符串加载X.509证书 + * + * @param certificateString 证书字符串 + * @param provider the provider + * @return X.509证书 + */ + public static X509Certificate loadX509FromString(String certificateString, String provider) { + try (ByteArrayInputStream inputStream = + new ByteArrayInputStream(certificateString.getBytes(StandardCharsets.UTF_8))) { + return loadX509FromStream(inputStream, provider); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static String getSerialNumber(X509Certificate certificate) { + return certificate.getSerialNumber().toString(16).toUpperCase(); + } + + + /** + * 转换输入流为字节数组 + * + * @param inputStream 输入流 + * @return 字节数组 + * @throws IOException 读取字节失败、关闭流失败等 + */ + public static byte[] toByteArray(InputStream inputStream) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int nRead; + byte[] data = new byte[DEFAULT_BUFFER_SIZE]; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + return buffer.toByteArray(); + } + + /** + * 转换输入流为字符串 + * + * @param inputStream 输入流 + * @return UTF-8编码的字符串 + * @throws IOException 读取字节失败、关闭流失败等 + */ + public static String ioToString(InputStream inputStream) throws IOException { + return new String(toByteArray(inputStream), StandardCharsets.UTF_8); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/hcy/common/config/wx/WxPayCustomConfig.java b/common/src/main/java/com/hcy/common/config/wx/WxPayCustomConfig.java new file mode 100644 index 0000000..04c5b1d --- /dev/null +++ b/common/src/main/java/com/hcy/common/config/wx/WxPayCustomConfig.java @@ -0,0 +1,385 @@ +package com.hcy.common.config.wx; + +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.config.WxPayHttpProxy; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.util.HttpProxyUtils; +import com.github.binarywang.wxpay.util.ResourcesUtils; +import com.github.binarywang.wxpay.v3.WxPayV3HttpClientBuilder; +import com.github.binarywang.wxpay.v3.auth.*; +import com.github.binarywang.wxpay.v3.util.PemUtils; +import lombok.Data; +import lombok.SneakyThrows; +import org.apache.commons.lang3.RegExUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.ssl.SSLContexts; + +import javax.net.ssl.SSLContext; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.util.Base64; + +@Data +public class WxPayCustomConfig extends WxPayConfig { + private static final String DEFAULT_PAY_BASE_URL = "https://api.mch.weixin.qq.com"; + private static final String PROBLEM_MSG = "证书文件【%s】有问题,请核实!"; + private static final String NOT_FOUND_MSG = "证书文件【%s】不存在,请核实!"; + + private String publicKey; + + private String publicKeyId; + + /** + * 微信支付接口请求地址域名部分. + */ + private String payBaseUrl = DEFAULT_PAY_BASE_URL; + + /** + * http请求连接超时时间. + */ + private int httpConnectionTimeout = 5000; + + /** + * http请求数据读取等待时间. + */ + private int httpTimeout = 10000; + + /** + * 公众号appid. + */ + private String appId; + /** + * 服务商模式下的子商户公众账号ID. + */ + private String subAppId; + /** + * 商户号. + */ + private String mchId; + /** + * 商户密钥. + */ + private String mchKey; + /** + * 企业支付密钥. + */ + private String entPayKey; + /** + * 服务商模式下的子商户号. + */ + private String subMchId; + /** + * 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数. + */ + private String notifyUrl; + /** + * 交易类型. + *
+     * JSAPI--公众号支付
+     * NATIVE--原生扫码支付
+     * APP--app支付
+     * 
+ */ + private String tradeType; + /** + * 签名方式. + * 有两种HMAC_SHA256 和MD5 + * + * @see com.github.binarywang.wxpay.constant.WxPayConstants.SignType + */ + private String signType; + private SSLContext sslContext; + /** + * p12证书base64编码 + */ + private String keyString; + /** + * p12证书文件的绝对路径或者以classpath:开头的类路径. + */ + private String keyPath; + + /** + * apiclient_key.pem证书base64编码 + */ + private String privateKeyString; + /** + * apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径. + */ + private String privateKeyPath; + + /** + * apiclient_cert.pem证书base64编码 + */ + private String privateCertString; + /** + * apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径. + */ + private String privateCertPath; + + /** + * apiclient_key.pem证书文件内容的字节数组. + */ + private byte[] privateKeyContent; + + /** + * apiclient_cert.pem证书文件内容的字节数组. + */ + private byte[] privateCertContent; + + /** + * apiV3 秘钥值. + */ + private String apiV3Key; + + /** + * apiV3 证书序列号值 + */ + private String certSerialNo; + /** + * 微信支付分serviceId + */ + private String serviceId; + + /** + * 微信支付分回调地址 + */ + private String payScoreNotifyUrl; + + + /** + * 微信支付分授权回调地址 + */ + private String payScorePermissionNotifyUrl; + + + private CloseableHttpClient apiV3HttpClient; + /** + * 私钥信息 + */ + private PrivateKey privateKey; + + /** + * 证书自动更新时间差(分钟),默认一分钟 + */ + private int certAutoUpdateTime = 60; + + /** + * p12证书文件内容的字节数组. + */ + private byte[] keyContent; + /** + * 微信支付是否使用仿真测试环境. + * 默认不使用 + */ + private boolean useSandboxEnv = false; + + /** + * 是否将接口请求日志信息保存到threadLocal中. + * 默认不保存 + */ + private boolean ifSaveApiData = false; + + private String httpProxyHost; + private Integer httpProxyPort; + private String httpProxyUsername; + private String httpProxyPassword; + + /** + * v3接口下证书检验对象,通过改对象可以获取到X509Certificate,进一步对敏感信息加密 + * 文档 + */ + private Verifier verifier; + + /** + * 返回所设置的微信支付接口请求地址域名. + * + * @return 微信支付接口请求地址域名 + */ + public String getPayBaseUrl() { + if (StringUtils.isEmpty(this.payBaseUrl)) { + return DEFAULT_PAY_BASE_URL; + } + + return this.payBaseUrl; + } + + @SneakyThrows + public Verifier getVerifier() { + if (verifier == null) { + //当改对象为null时,初始化api v3的请求头 + initApiV3HttpClient(); + } + return verifier; + } + + /** + * 初始化ssl. + * + * @return the ssl context + * @throws WxPayException the wx pay exception + */ + public SSLContext initSSLContext() throws WxPayException { + if (StringUtils.isBlank(this.getMchId())) { + throw new WxPayException("请确保商户号mchId已设置"); + } + + try (InputStream inputStream = this.loadConfigInputStream(this.keyString, this.getKeyPath(), + this.keyContent, "p12证书");) { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + char[] partnerId2charArray = this.getMchId().toCharArray(); + keystore.load(inputStream, partnerId2charArray); + this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build(); + return this.sslContext; + } catch (Exception e) { + throw new WxPayException("证书文件有问题,请核实!", e); + } + + } + + /** + * 初始化api v3请求头 自动签名验签 + * 方法参照微信官方https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient + * + * @return org.apache.http.impl.client.CloseableHttpClient + * @author doger.wang + **/ + public CloseableHttpClient initApiV3HttpClient() throws WxPayException { + if (StringUtils.isBlank(this.getApiV3Key())) { + throw new WxPayException("请确保apiV3Key值已设置"); + } + + InputStream keyInputStream = this.loadConfigInputStream(this.getPrivateKeyString(), this.getPrivateKeyPath(), + this.privateKeyContent, "privateKeyPath"); + InputStream certInputStream = this.loadConfigInputStream(this.getPrivateCertString(), this.getPrivateCertPath(), + this.privateCertContent, "privateCertPath"); + try { + PrivateKey merchantPrivateKey = PemUtils.loadPrivateKey(keyInputStream); + X509Certificate certificate = PemUtils.loadCertificate(certInputStream); + if (StringUtils.isBlank(this.getCertSerialNo())) { + this.certSerialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + } + //构造Http Proxy正向代理 + WxPayHttpProxy wxPayHttpProxy = getWxPayHttpProxy(); + Verifier certificatesVerifier; + if (StringUtils.isBlank(this.getPublicKeyId()) || StringUtils.isBlank(getPublicKey())) { + certificatesVerifier = new AutoUpdateCertificatesVerifier( + new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)), + this.getApiV3Key().getBytes(StandardCharsets.UTF_8), this.getCertAutoUpdateTime(), wxPayHttpProxy); + } else { + PublicKey publicKey = PemUtil.loadPublicKeyFromPath(getPublicKey()); + certificatesVerifier = new CustomPublicKeyVerifier(publicKey, getPublicKeyId()); + } + WxPayV3HttpClientBuilder wxPayV3HttpClientBuilder = WxPayV3HttpClientBuilder.create() + .withMerchant(mchId, certSerialNo, merchantPrivateKey) + .withValidator(new WxPayValidator(certificatesVerifier)); + //初始化V3接口正向代理设置 + HttpProxyUtils.initHttpProxy(wxPayV3HttpClientBuilder, wxPayHttpProxy); + + CloseableHttpClient httpClient = wxPayV3HttpClientBuilder.build(); + + this.apiV3HttpClient = httpClient; + this.verifier = certificatesVerifier; + this.privateKey = merchantPrivateKey; + + return httpClient; + } catch (Exception e) { + throw new WxPayException("v3请求构造异常!", e); + } + } + + /** + * 初始化一个WxPayHttpProxy对象 + * + * @return 返回封装的WxPayHttpProxy对象。如未指定代理主机和端口,则默认返回null + */ + private WxPayHttpProxy getWxPayHttpProxy() { + if (StringUtils.isNotBlank(this.getHttpProxyHost()) && this.getHttpProxyPort() > 0) { + return new WxPayHttpProxy(getHttpProxyHost(), getHttpProxyPort(), getHttpProxyUsername(), getHttpProxyPassword()); + } + return null; + } + + private InputStream loadConfigInputStream(String configString, String configPath, byte[] configContent, + String fileName) throws WxPayException { + InputStream inputStream; + if (configContent != null) { + inputStream = new ByteArrayInputStream(configContent); + } else if (StringUtils.isNotEmpty(configString)) { + configContent = Base64.getDecoder().decode(configString); + inputStream = new ByteArrayInputStream(configContent); + } else { + if (StringUtils.isBlank(configPath)) { + throw new WxPayException("请确保证书文件地址【" + fileName + "】或者内容已配置"); + } + inputStream = this.loadConfigInputStream(configPath); + } + return inputStream; + } + + + /** + * 从配置路径 加载配置 信息(支持 classpath、本地路径、网络url) + * + * @param configPath 配置路径 + * @return . + * @throws WxPayException . + */ + private InputStream loadConfigInputStream(String configPath) throws WxPayException { + String fileHasProblemMsg = String.format(PROBLEM_MSG, configPath); + String fileNotFoundMsg = String.format(NOT_FOUND_MSG, configPath); + + final String prefix = "classpath:"; + InputStream inputStream; + if (configPath.startsWith(prefix)) { + String path = RegExUtils.removeFirst(configPath, prefix); + if (!path.startsWith("/")) { + path = "/" + path; + } + + try { + inputStream = ResourcesUtils.getResourceAsStream(path); + if (inputStream == null) { + throw new WxPayException(fileNotFoundMsg); + } + + return inputStream; + } catch (Exception e) { + throw new WxPayException(fileNotFoundMsg, e); + } + } + + if (configPath.startsWith("http://") || configPath.startsWith("https://")) { + try { + inputStream = new URL(configPath).openStream(); + if (inputStream == null) { + throw new WxPayException(fileNotFoundMsg); + } + return inputStream; + } catch (IOException e) { + throw new WxPayException(fileNotFoundMsg, e); + } + } else { + try { + File file = new File(configPath); + if (!file.exists()) { + throw new WxPayException(fileNotFoundMsg); + } + + return Files.newInputStream(file.toPath()); + } catch (IOException e) { + throw new WxPayException(fileHasProblemMsg, e); + } + } + + } +} \ No newline at end of file diff --git a/common/src/main/java/com/hcy/common/dto/staff/StaffDto.java b/common/src/main/java/com/hcy/common/dto/staff/StaffDto.java index ceed274..bb65017 100644 --- a/common/src/main/java/com/hcy/common/dto/staff/StaffDto.java +++ b/common/src/main/java/com/hcy/common/dto/staff/StaffDto.java @@ -33,4 +33,8 @@ public class StaffDto implements Serializable { private Integer isReceiveOrder; //是否可以接单:0-可以;1-不可接单 private Integer isOrder; //师傅是否接单:0-接单中;1-休息中; + private Long goodsCategoryId; //服务分类id + private Long staffId; //师傅id + + } diff --git a/common/src/main/java/com/hcy/common/entity/order/Order.java b/common/src/main/java/com/hcy/common/entity/order/Order.java index 16a3316..e965339 100644 --- a/common/src/main/java/com/hcy/common/entity/order/Order.java +++ b/common/src/main/java/com/hcy/common/entity/order/Order.java @@ -61,4 +61,5 @@ public class Order implements Serializable { private Long userCouponId; //用户领取优惠券id private BigDecimal deductionMoney; //抵扣金额 private Double addScore; + private String serveImg; //服务图片 } \ No newline at end of file diff --git a/common/src/main/java/com/hcy/common/entity/staff/Staff.java b/common/src/main/java/com/hcy/common/entity/staff/Staff.java index 99b65d5..adcf970 100644 --- a/common/src/main/java/com/hcy/common/entity/staff/Staff.java +++ b/common/src/main/java/com/hcy/common/entity/staff/Staff.java @@ -38,19 +38,14 @@ public class Staff implements Serializable { private Integer isDelete; private String headPortrait; //头像图片 - private String idCardImg; //身份证正反面图片 逗号隔开 - private String idCard; //身份证号 private Integer age; //年龄 - private String physicalExamination; //体检报告 多图片逗号隔开 private Double score; //师傅评分 默认评分:5 private Double addScore; //追加评分 private Integer isReceiveOrder; //是否可以接单:0-可以;1-不可接单 private Integer isOrder; //师傅是否接单:0-接单中;1-休息中; - private Integer isAuthentication; //是否实名认证:1-已实名认证;0-未实名认证; - private BigDecimal canWithdrawCommission; //可提现佣金 - private BigDecimal alreadyWithdraw; //已提现佣金 - private Integer isOperational; //是否运营师傅:0-不是 1-是 - private String workStartTime; //工作开始时间 - private String workEndTime; //工作结束时间 + +// private Integer isOperational; //是否运营师傅:0-不是 1-是 +// private String workStartTime; //工作开始时间 +// private String workEndTime; //工作结束时间 } \ No newline at end of file diff --git a/common/src/main/java/com/hcy/common/mapper/category/GoodsCategoryMapper.java b/common/src/main/java/com/hcy/common/mapper/category/GoodsCategoryMapper.java index d4e5bfe..363eda2 100644 --- a/common/src/main/java/com/hcy/common/mapper/category/GoodsCategoryMapper.java +++ b/common/src/main/java/com/hcy/common/mapper/category/GoodsCategoryMapper.java @@ -25,6 +25,4 @@ public interface GoodsCategoryMapper extends IBaseMapper { */ List getCouponCorrelationGoodsCategory(@Param("couponId") long couponId); - - } diff --git a/common/src/main/resources/mapper/OrderMapper.xml b/common/src/main/resources/mapper/OrderMapper.xml index 7371924..edf1dcb 100644 --- a/common/src/main/resources/mapper/OrderMapper.xml +++ b/common/src/main/resources/mapper/OrderMapper.xml @@ -53,49 +53,52 @@ diff --git a/common/src/main/resources/mapper/StaffMapper.xml b/common/src/main/resources/mapper/StaffMapper.xml index 4aba478..6157bbc 100644 --- a/common/src/main/resources/mapper/StaffMapper.xml +++ b/common/src/main/resources/mapper/StaffMapper.xml @@ -27,6 +27,9 @@ left join la_user b on a.user_id = b.id a.is_delete = 0 + + and a.id != #{form.staffId} + and a.status = #{form.status} @@ -74,6 +77,9 @@ AND ( appoint_time_start > ${form.appointTimeStart} AND appoint_time_end < ${form.appointTimeEnd} )) or a.is_operational = 1) or a.is_operational = 1) + + and FIND_IN_SET(#{form.goodsCategoryId},a.goods_category_ids) + order by a.create_time desc diff --git a/front/src/main/java/com/hcy/front/config/wxpay/WxPayConfiguration.java b/front/src/main/java/com/hcy/front/config/wxpay/WxPayConfiguration.java index 1219295..1bec7bf 100644 --- a/front/src/main/java/com/hcy/front/config/wxpay/WxPayConfiguration.java +++ b/front/src/main/java/com/hcy/front/config/wxpay/WxPayConfiguration.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; +import com.hcy.common.config.wx.WxPayCustomConfig; import com.hcy.common.entity.pay.DevPay; import com.hcy.common.entity.system.SystemConfig; import com.hcy.common.entity.wxpay.SystemWxPayConfig; @@ -71,7 +72,7 @@ public class WxPayConfiguration { private WxPayService getWxPayServiceConfig(String chancel){ Boolean flag = Boolean.FALSE; - WxPayConfig payConfig = new WxPayConfig(); + WxPayCustomConfig payConfig = new WxPayCustomConfig(); DevPay devPay = devPayMapper.getEntityByPayWay(OrderPlayTypeEnum.WECHAT_PAY.getType()); String config = devPay.getConfig(); SystemWxPayConfig systemWxPayConfig = JSON.parseObject(config, SystemWxPayConfig.class); @@ -86,6 +87,16 @@ public class WxPayConfiguration { payConfig.setPrivateCertContent(StringUtils.trimToNull(systemWxPayConfig.getApiclientCert()).getBytes()); flag = Boolean.TRUE; } + payConfig.setPublicKeyId("PUB_KEY_ID_0117052034742025012300326100001464"); + payConfig.setPublicKey("-----BEGIN PUBLIC KEY-----\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xtJgD6ML1dL3AnCHJ7G\n" + + "lwoSpdZKCb0yoL3D0la47yXgiFcwA+PXum/d5uTBQ3rxXIV1YMPNF7JhA2nPYC9O\n" + + "xTnA+bvAL9e4EP9x3Ocs5Uc9J+p/NxO+FcbD8Qbp6eDM2Rn5iir3TMze0ppMwDCE\n" + + "LtVlSCo5DysLjuL6Ub71QBN0aaOJ5SFQtyRXTizm+sDvL7JvHRbOy+lJsyIN83EW\n" + + "NzWuBMUR5gs7KgCRPSQvAOIXGcfxYP1kYlCbkYHzACDhpKB3ZDQHWIlwVMuCsYb/\n" + + "O4/0gPK/xizNdtjM2SDz/IijWOfVhBb9rup+hccbns4Zi/8hn0+CiiZpBVbWxak2\n" + + "iQIDAQAB\n" + + "-----END PUBLIC KEY-----\n"); // 可以指定是否使用沙箱环境 payConfig.setUseSandboxEnv(false); WxPayService wxPayService = new WxPayServiceImpl(); diff --git a/front/src/main/java/com/hcy/front/controller/OrderController.java b/front/src/main/java/com/hcy/front/controller/OrderController.java index 9fb30ec..172c719 100644 --- a/front/src/main/java/com/hcy/front/controller/OrderController.java +++ b/front/src/main/java/com/hcy/front/controller/OrderController.java @@ -154,6 +154,18 @@ public class OrderController { iOrderService.verificationOrder(id, userId); } + /** + * 师傅核销服务订单 + * + * @return Object + */ + @ApiOperation(value = "订单管理 - 师傅核销服务订单") + @GetMapping("/staff/verification") + public void confirmGoods(@Validated @RequestParam("id") Long id, @RequestParam("code") String code) { + Integer userId = FrontThreadLocal.getUserId(); + iOrderService.staffConfirmGoods(id, userId, code); + } + /** * 订单删除 * @@ -201,4 +213,11 @@ public class OrderController { CancelOrderConfigDetailVo cancelOrderConfigByOrder = iOrderService.getCancelOrderConfigByOrder(orderId,goodsId); return AjaxResult.success(cancelOrderConfigByOrder == null ? JSON.toJSON(new Object()) : cancelOrderConfigByOrder); } + + @ApiOperation(value = "订单管理 - 师傅上传服务图片") + @PostMapping("/staff/uploadServiceImg") + public void uploadServiceImg(@RequestBody OrderParam orderParam) {; + iOrderService.uploadServiceImg(orderParam); + } + } diff --git a/front/src/main/java/com/hcy/front/service/order/IOrderService.java b/front/src/main/java/com/hcy/front/service/order/IOrderService.java index 9caa878..e6f8ee0 100644 --- a/front/src/main/java/com/hcy/front/service/order/IOrderService.java +++ b/front/src/main/java/com/hcy/front/service/order/IOrderService.java @@ -93,4 +93,12 @@ public interface IOrderService { * @return cancelOrderConfigByOrder */ CancelOrderConfigDetailVo getCancelOrderConfigByOrder(Long orderId,Long goodsId); + + /** + * 师傅上传服务图片 + * @param orderParam + */ + void uploadServiceImg(OrderParam orderParam); + + void staffConfirmGoods(Long id, Integer userId, String code); } diff --git a/front/src/main/java/com/hcy/front/service/order/impl/OrderServiceImpl.java b/front/src/main/java/com/hcy/front/service/order/impl/OrderServiceImpl.java index 018b152..2846fda 100644 --- a/front/src/main/java/com/hcy/front/service/order/impl/OrderServiceImpl.java +++ b/front/src/main/java/com/hcy/front/service/order/impl/OrderServiceImpl.java @@ -300,6 +300,9 @@ public class OrderServiceImpl extends ServiceImpl implements vo.setProvince(regionMap.get(item.getProvinceId())); vo.setCity(regionMap.get(item.getCityId())); vo.setDistrict(regionMap.get(item.getDistrictId())); + if(vo.getOrderStatus() == OrderStatusEnum.FINISHED.getStatus()){ + vo.setUploadServiceImgBtn(1); //当订单状态为已完成的时候,显示上传服务图片按钮 + } list.add(vo); } return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list); @@ -311,8 +314,8 @@ public class OrderServiceImpl extends ServiceImpl implements Integer pageSize = pageParam.getPageSize(); Long userId = Long.valueOf(params.get("userId")); List orderStatusList; - if (StringUtils.isNotEmpty(params.get("params"))) { - orderStatusList = Arrays.asList(params.get("params").split(",")); + if (StringUtils.isNotEmpty(params.get("orderStatus"))) { + orderStatusList = Arrays.asList(params.get("orderStatus").split(",")); } else { orderStatusList = Arrays.asList(String.valueOf(OrderStatusEnum.SERVICING.getStatus()) , String.valueOf(OrderStatusEnum.RESERVE.getStatus()) @@ -381,6 +384,10 @@ public class OrderServiceImpl extends ServiceImpl implements vo.setWeekDay(TimeUtil.getWeekDay(model.getAppointTimeStart())); vo.setPayTime(model.getPayTime() != null ? model.getPayTime().toString() : ""); + if(model.getServeImg() != null){ + vo.setServiceImages(Arrays.asList(model.getServeImg().split(","))); //将数组转成列表返回给前端 + } + if(flag == null || flag == 0){ vo.setAppointTime(TimeUtil.timestampToDate(model.getAppointTimeStart(), "yyyy-MM-dd")); }else if(flag == 1){ @@ -515,9 +522,12 @@ public class OrderServiceImpl extends ServiceImpl implements } } + // 获取地址 + UserAddress userAddress = addressMapper.selectById(orderParam.getAddressId()); + Assert.notNull(userAddress, "用户收货地址不能为空"); //校验订单地址是否在服务城市 OpenCity openCity = openCityMapper.selectOne(new LambdaQueryWrapper() - .eq(OpenCity::getCityId, orderParam.getCityId()) + .eq(OpenCity::getCityId, userAddress.getCityId()) .eq(OpenCity::getIsDelete, GlobalConstant.NOT_DELETE)); if(openCity == null){ throw new OperateException("该订单地址未开通家政服务"); @@ -550,9 +560,7 @@ public class OrderServiceImpl extends ServiceImpl implements // 默认未核销 model.setVerificationStatus(OrderVerificationStatusEnum.WAIT_VERIFICATION.getStatus()); - // 获取地址 - UserAddress userAddress = addressMapper.selectById(orderParam.getAddressId()); - Assert.notNull(userAddress, "用户收货地址不能为空"); + model.setContact(userAddress.getContact()); model.setMobile(userAddress.getMobile()); model.setProvinceId(userAddress.getProvinceId()); @@ -678,17 +686,9 @@ public class OrderServiceImpl extends ServiceImpl implements if(model.getOrderAmount().compareTo(new BigDecimal("0")) == 0){ model.setPayStatus(OrderPayStatusEnum.PAY.getStatus());//支付状态;已支付; model.setPayTime(TimeUtil.timestamp()); - model.setOrderStatus(OrderStatusEnum.SERVICING.getStatus()); //订单状态预约中 - model.setIsDispatch(OrderDispatchEnum.IS_DISPATCH.getStatus()); //付完款直接已派单 - -// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { -// @Override -// public void afterCommit() { -// //通知师傅接单 -// staffReceiveOrderService.notificationStaff(model.getId()); -// } -// }); + model.setOrderStatus(OrderStatusEnum.RESERVE.getStatus()); //订单状态预约中 } + model.setIsDispatch(OrderDispatchEnum.NOT_DISPATCH.getStatus()); orderMapper.insert(model); //零元购新增记录订单日志 @@ -964,7 +964,7 @@ public class OrderServiceImpl extends ServiceImpl implements } //不是运营师傅才做限制 - if(staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode()){ + if(staff.getUserId() != null){ //判断是否存在服务中的订单 List orderList = orderMapper.selectList(new QueryWrapper() .eq("is_delete", GlobalConstant.NOT_DELETE) @@ -984,7 +984,7 @@ public class OrderServiceImpl extends ServiceImpl implements throw new OperateException("该预约时间段内,存在时间冲突,不能确认该服务"); } - if(model.getAppointTimeStart() > TimeUtil.timestamp()){ + if(model.getAppointTimeStart() > (TimeUtil.timestamp() + 3600)){ throw new OperateException("未到预约时间,不可开始服务"); } } @@ -1061,9 +1061,9 @@ public class OrderServiceImpl extends ServiceImpl implements model.setTransactionId(queryOrderV3.getTransactionId()); model.setUpdateTime(TimeUtil.timestamp()); model.setCreateTime(null); - model.setOrderStatus(OrderStatusEnum.SERVICING.getStatus()); //下单且支付成功后就变到已预约 + model.setOrderStatus(OrderStatusEnum.RESERVE.getStatus()); //下单且支付成功后就变到已预约 model.setVerificationStatus(OrderVerificationStatusEnum.WAIT_VERIFICATION.getStatus()); - model.setIsDispatch(OrderDispatchEnum.IS_DISPATCH.getStatus()); //付完款直接已派单 + //model.setIsDispatch(OrderDispatchEnum.IS_DISPATCH.getStatus()); //付完款直接已派单 orderMapper.updateById(model); // 记录日志 orderLogService.saveOrderLog(orderId, model.getUserId(), OrderLogEnum.USER_PAY_ORDER.getDesc()); @@ -1351,5 +1351,122 @@ public class OrderServiceImpl extends ServiceImpl implements return cancelOrderConfigDetailVo; } + /** + * 师傅上传服务图片 + * + * @param orderParam + */ + @Override + public void uploadServiceImg(OrderParam orderParam) { + Order model = orderMapper.selectOne( + new QueryWrapper() + .eq("id", orderParam.getId()) + .last("limit 1")); + Assert.notNull(model, "数据不存在!"); + if(model.getOrderStatus() == OrderStatusEnum.SERVICING.getStatus() || + model.getOrderStatus() == OrderStatusEnum.FINISHED.getStatus()){ + BeanUtils.copyProperties(orderParam,model); + model.setServeImg(String.join(",", orderParam.getServiceImages())); //服务图片 + orderMapper.updateById(model); + }else{ + throw new OperateException("当前订单状态无法上传服务图片"); + } + } + @Override + @Transactional + public void staffConfirmGoods(Long id, Integer userId, String code) { + Order model = orderMapper.selectOne( + new QueryWrapper() + .eq("id", id) + .last("limit 1")); + Assert.notNull(model, "数据不存在!"); + if (OrderStatusEnum.SERVICING.getStatus() != model.getOrderStatus()) { + throw new OperateException("只有已预约的订单才能进行核销"); + } + String verificationCode = model.getVerificationCode(); + if (!verificationCode.equalsIgnoreCase(code)) { + throw new OperateException("核销码错误,请重新输入"); + } + model.setVerificationStatus(OrderVerificationStatusEnum.VERIFICATION.getStatus()); + model.setOrderStatus(OrderStatusEnum.FINISHED.getStatus()); + model.setFinishTime(TimeUtil.timestamp()); + model.setUpdateTime(TimeUtil.timestamp()); + orderMapper.updateById(model); + + //获取服务信息 +// OrderGoods orderGoods = orderGoodsService.getByOrderId(model.getId()); +// BigDecimal defaultPrice = new BigDecimal("0"); + + /*//更新用户积分 + User user = userMapper.selectOne( + new QueryWrapper() + .eq("id", userId) + .last("limit 1")); + user.setIntegral(user.getIntegral() + orderGoods.getIntegral()); + userMapper.updateById(user);*/ + + //创建分销佣金 +// if (model.getDistrictId() != null && model.getDistrictId() != 0) { +// //获取分销商信息 +// QueryWrapper distributorQueryWrapper = new QueryWrapper<>(); +// distributorQueryWrapper.eq("is_delete", GlobalConstant.NOT_DELETE); +// distributorQueryWrapper.eq("id", model.getDistributorId()); +// Distributor distributor = distributorMapper.selectOne(distributorQueryWrapper); +// //组装参数 +// DistributorCommission distributorCommission = new DistributorCommission(); +// distributorCommission.setOrderId(model.getId()); +// +// if (distributor != null) { +// //支付金额不等于零时或者服务金额为零时 +// if (model.getOrderAmount().compareTo(defaultPrice) > 0 && +// orderGoods.getDistributorCommissionRate().compareTo(defaultPrice) > 0 && +// distributor.getCommissionRate().compareTo(defaultPrice) > 0) { +// //计算佣金 +// BigDecimal goodsCommissionRate = orderGoods.getDistributorCommissionRate().divide(new BigDecimal("100")); +// BigDecimal distributorRate = distributor.getCommissionRate().divide(new BigDecimal("10.00")); +// BigDecimal result = orderGoods.getTotalPayPrice().multiply(goodsCommissionRate).multiply(distributorRate).setScale(2, RoundingMode.HALF_UP); +// //如果结算金额小于0.01时 佣金为0 +// if (result.compareTo(new BigDecimal("0.01")) < 0) { +// distributorCommission.setCommission(defaultPrice); +// } else { +// distributorCommission.setCommission(result); +// } +// } else { +// distributorCommission.setCommission(defaultPrice); +// } +// distributorCommission.setDistributorId(distributor.getId()); +// distributorCommission.setDistributorCommissionRate(orderGoods.getDistributorCommissionRate()); +// distributorCommission.setGoodsCommissionRate(orderGoods.getGoodsCommissionRate()); +// distributorCommission.setCreateTime(TimeUtil.nowDate()); +// distributorCommission.setStatus(DistributorCommissionStatusEnum.FREEZE.getCode()); +// distributorCommission.setIsDelete(GlobalConstant.NOT_DELETE); +// distributorCommissionMapper.insert(distributorCommission); +// } +// } + + //后台指派师傅 追加评分 +// if(model.getAddScore() != null){ +// Staff staff = staffService.getById(model.getStaffId()); +// staff.setAddScore(staff.getAddScore() + model.getAddScore()); +// staffMapper.updateById(staff); +// } + + //创建师傅佣金 +// StaffCommission staffCommission = new StaffCommission(); +// staffCommission.setStaffId(model.getStaffId()); +// staffCommission.setOrderId(model.getId()); +// staffCommission.setGoodsCommissionRate(orderGoods.getStaffCommissionRate()); + //师傅抽成 +// if(orderGoods.getStaffCommissionRate().compareTo(defaultPrice) > 0){ +// staffCommission.setCommission(model.getOrderAmount().multiply(orderGoods.getStaffCommissionRate() +// .divide(new BigDecimal("100")))); +// }else{ +// staffCommission.setCommission(defaultPrice); +// } +// staffCommission.setCreateTime(TimeUtil.nowDate()); +// staffCommissionMapper.insert(staffCommission); + + orderLogService.saveOrderLog(id, userId.longValue(), OrderLogEnum.USER_VERIFICATION.getDesc()); + } } diff --git a/front/src/main/java/com/hcy/front/service/staff/impl/StaffReceiveOrderServiceImpl.java b/front/src/main/java/com/hcy/front/service/staff/impl/StaffReceiveOrderServiceImpl.java index f9a8f88..f38acd1 100644 --- a/front/src/main/java/com/hcy/front/service/staff/impl/StaffReceiveOrderServiceImpl.java +++ b/front/src/main/java/com/hcy/front/service/staff/impl/StaffReceiveOrderServiceImpl.java @@ -353,43 +353,43 @@ public class StaffReceiveOrderServiceImpl extends ServiceImpl orderList = orderMapper.selectList(new QueryWrapper() - .eq("is_delete", GlobalConstant.NOT_DELETE) - .eq("staff_id",staffId) - .and(query -> query.ne("order_status", OrderStatusEnum.FINISHED.getStatus()) - .ne("order_status", OrderStatusEnum.CLOSE.getStatus()))); - Double score = staff.getScore(); - if(score >= 4.5 && orderList.size() >= 5){ - msg = "已达到当前评分接单上限"; - }else if(score >= 4 && score < 4.5 && orderList.size() >= 3){ - msg = "已达到当前评分接单上限"; - }else if(score >= 3.5 && score <4 && orderList.size() >= 2){ - msg = "已达到当前评分接单上限"; - } - if(StringUtil.isNotEmpty(msg)){ - throw new OperateException(msg); - } - - //判断当前接单时间和已接订单是否冲突 - for (Order item : orderList) { - long startTime = item.getAppointTimeStart() - 3600; - long endTime = item.getAppointTimeEnd() + 3600; - //当前订单预约的开始时间和结束时间不可在已接订单之间且只能接已接订单前后一个小时的订单 - if(TimeUtil.isEffectiveDate(model.getAppointTimeStart(),startTime,endTime) || - TimeUtil.isEffectiveDate(model.getAppointTimeEnd(),startTime,endTime)){ - throw new OperateException("当前订单和已接订单上门时间冲突"); - } - } - } +// if(staff.getIsOperational() == StaffStatusEnum.NOT_OPERATIONAL_STAFF.getCode()){ +// if(staff.getIsReceiveOrder() == StaffStatusEnum.ORDER_NOT_AVAILABLE.getCode()){ +// throw new OperateException("当前属于不可接单状态,请联系客服"); +// }else if(staff.getIsOrder() == StaffStatusEnum.REST.getCode()){ +// throw new OperateException("休息中,不可接单"); +// } +// +// String msg = ""; +// //判断师傅当前分数是否可以接单和接单数量是否达到上限 +// List orderList = orderMapper.selectList(new QueryWrapper() +// .eq("is_delete", GlobalConstant.NOT_DELETE) +// .eq("staff_id",staffId) +// .and(query -> query.ne("order_status", OrderStatusEnum.FINISHED.getStatus()) +// .ne("order_status", OrderStatusEnum.CLOSE.getStatus()))); +// Double score = staff.getScore(); +// if(score >= 4.5 && orderList.size() >= 5){ +// msg = "已达到当前评分接单上限"; +// }else if(score >= 4 && score < 4.5 && orderList.size() >= 3){ +// msg = "已达到当前评分接单上限"; +// }else if(score >= 3.5 && score <4 && orderList.size() >= 2){ +// msg = "已达到当前评分接单上限"; +// } +// if(StringUtil.isNotEmpty(msg)){ +// throw new OperateException(msg); +// } +// +// //判断当前接单时间和已接订单是否冲突 +// for (Order item : orderList) { +// long startTime = item.getAppointTimeStart() - 3600; +// long endTime = item.getAppointTimeEnd() + 3600; +// //当前订单预约的开始时间和结束时间不可在已接订单之间且只能接已接订单前后一个小时的订单 +// if(TimeUtil.isEffectiveDate(model.getAppointTimeStart(),startTime,endTime) || +// TimeUtil.isEffectiveDate(model.getAppointTimeEnd(),startTime,endTime)){ +// throw new OperateException("当前订单和已接订单上门时间冲突"); +// } +// } +// } //更改订单状态 model.setStaffMobile(staff.getMobile()); diff --git a/front/src/main/java/com/hcy/front/service/staff/impl/StaffServiceImpl.java b/front/src/main/java/com/hcy/front/service/staff/impl/StaffServiceImpl.java index 65ec627..c95271a 100644 --- a/front/src/main/java/com/hcy/front/service/staff/impl/StaffServiceImpl.java +++ b/front/src/main/java/com/hcy/front/service/staff/impl/StaffServiceImpl.java @@ -398,7 +398,7 @@ public class StaffServiceImpl extends ServiceImpl implements //已实名认证成功 if(staff != null){ staffCenterVo.setStaffId(staff.getId()); - staffCenterVo.setAuthenticationStatus(staff.getIsAuthentication()); +// staffCenterVo.setAuthenticationStatus(staff.getIsAuthentication()); staffCenterVo.setIsOrder(staff.getIsOrder()); BeanUtils.copyProperties(staff,staffCenterVo); //体检报告 @@ -407,26 +407,26 @@ public class StaffServiceImpl extends ServiceImpl implements .eq("staff_id", staff.getId()) .orderByDesc("create_time").last("limit 1")); //已提交体检报告 - if(StringUtils.isNotEmpty(staff.getPhysicalExamination())){ - staffCenterVo.setPhysicalExaminationStatus(1); - staffCenterVo.setIsReceiveOrder(staff.getIsReceiveOrder()); - if(staffPhysicalExamination != null){ - staffCenterVo.setIsReadr(staffPhysicalExamination.getIsRead()); - }else{ - staffCenterVo.setIsReadr(1); - } - }else{ - if(staffPhysicalExamination != null){ - if(staffPhysicalExamination.getStatus() == 0){ - staffCenterVo.setPhysicalExaminationStatus(2); - }else if(staffPhysicalExamination.getStatus() == 2){ - staffCenterVo.setPhysicalExaminationStatus(3); - staffCenterVo.setRefuseReason(staffPhysicalExamination.getRefuseReason()); - } - }else{ - staffCenterVo.setPhysicalExaminationStatus(0); - } - } +// if(StringUtils.isNotEmpty(staff.getPhysicalExamination())){ +// staffCenterVo.setPhysicalExaminationStatus(1); +// staffCenterVo.setIsReceiveOrder(staff.getIsReceiveOrder()); +// if(staffPhysicalExamination != null){ +// staffCenterVo.setIsReadr(staffPhysicalExamination.getIsRead()); +// }else{ +// staffCenterVo.setIsReadr(1); +// } +// }else{ +// if(staffPhysicalExamination != null){ +// if(staffPhysicalExamination.getStatus() == 0){ +// staffCenterVo.setPhysicalExaminationStatus(2); +// }else if(staffPhysicalExamination.getStatus() == 2){ +// staffCenterVo.setPhysicalExaminationStatus(3); +// staffCenterVo.setRefuseReason(staffPhysicalExamination.getRefuseReason()); +// } +// }else{ +// staffCenterVo.setPhysicalExaminationStatus(0); +// } +// } staffCenterVo.setAuthenticationStatus(StaffStatusEnum.AUTHENTICATION.getCode()); return staffCenterVo; } @@ -496,8 +496,8 @@ public class StaffServiceImpl extends ServiceImpl implements Assert.notNull(staff,"该师傅不存在"); StaffWallet staffWallet = new StaffWallet(); - staffWallet.setAlreadyWithdraw(staff.getAlreadyWithdraw()); - staffWallet.setCanWithdrawCommission(staff.getCanWithdrawCommission()); +// staffWallet.setAlreadyWithdraw(staff.getAlreadyWithdraw()); +// staffWallet.setCanWithdrawCommission(staff.getCanWithdrawCommission()); BigDecimal sum = staffCommissionMapper.sum("commission", new QueryWrapper() .eq("is_delete", GlobalConstant.NOT_DELETE) @@ -873,12 +873,12 @@ public class StaffServiceImpl extends ServiceImpl implements Assert.notNull(staff,"师傅不存在"); UserAuth userAuth = userAuthMapper.queryUserAuthByUserId(staff.getUserId()); Assert.notNull(userAuth,"师傅未绑定用户或绑定用户不存在"); - - if(withdrawCommissionParam.getWithdrawMoney().compareTo(new BigDecimal("0.1")) < 0){ - throw new OperateException("提现金额必须大于0.1元"); - }else if (staff.getCanWithdrawCommission().compareTo(withdrawCommissionParam.getWithdrawMoney()) < 0){ - throw new OperateException("账户余额不足"); - } +// +// if(withdrawCommissionParam.getWithdrawMoney().compareTo(new BigDecimal("0.1")) < 0){ +// throw new OperateException("提现金额必须大于0.1元"); +// }else if (staff.getCanWithdrawCommission().compareTo(withdrawCommissionParam.getWithdrawMoney()) < 0){ +// throw new OperateException("账户余额不足"); +// } String staffSn = SnUtils.getCommissionWithdrawSn(); String staffDetailSn = SnUtils.getCommissionWithdrawSn(); @@ -924,7 +924,7 @@ public class StaffServiceImpl extends ServiceImpl implements TransferCreateResult transfer = merchantTransferService.createTransfer(transferCreateRequest); withdrawCommission.setBatchId(transfer.getBatchId()); withdrawCommission.setStatus(DistributorWithdrawStatusEnum.WITHDRAW.getStatus()); - staff.setCanWithdrawCommission(staff.getCanWithdrawCommission().subtract(withdrawCommissionParam.getWithdrawMoney())); +// staff.setCanWithdrawCommission(staff.getCanWithdrawCommission().subtract(withdrawCommissionParam.getWithdrawMoney())); staffMapper.updateById(staff); commissionWithdrawMapper.updateById(withdrawCommission); @@ -970,7 +970,6 @@ public class StaffServiceImpl extends ServiceImpl implements public List queryOperationalStaff() { return staffMapper.selectList(new LambdaQueryWrapper() .eq(Staff::getIsDelete, GlobalConstant.NOT_DELETE) - .eq(Staff::getIsOrder,StaffStatusEnum.ORDER_AVAILABLE.getCode()) - .eq(Staff::getIsOperational, StaffStatusEnum.OPERATIONAL_STAFF.getCode())); + .eq(Staff::getIsOrder,StaffStatusEnum.ORDER_AVAILABLE.getCode())); } } diff --git a/front/src/main/java/com/hcy/front/validate/order/OrderParam.java b/front/src/main/java/com/hcy/front/validate/order/OrderParam.java index 214af67..423e99c 100644 --- a/front/src/main/java/com/hcy/front/validate/order/OrderParam.java +++ b/front/src/main/java/com/hcy/front/validate/order/OrderParam.java @@ -10,6 +10,7 @@ import javax.validation.constraints.DecimalMin; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.math.BigDecimal; +import java.util.List; /** * 订单参数 @@ -176,4 +177,7 @@ public class OrderParam implements Serializable { @ApiModelProperty(value = "是否使用积分抵扣金额:1是 0否") private Long isIntegral; + + private List serviceImages; //服务图片 + } diff --git a/front/src/main/java/com/hcy/front/vo/order/OrderDetailVo.java b/front/src/main/java/com/hcy/front/vo/order/OrderDetailVo.java index cea808f..f76107f 100644 --- a/front/src/main/java/com/hcy/front/vo/order/OrderDetailVo.java +++ b/front/src/main/java/com/hcy/front/vo/order/OrderDetailVo.java @@ -11,6 +11,7 @@ import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; +import java.util.List; /** * OrderVo @@ -144,4 +145,7 @@ public class OrderDetailVo implements Serializable { private BigDecimal projectCost; //项目费用 private OrderRefundDetailVo orderRefundDetailVo; //退款详情 + + private List serviceImages; //服务图片 + } diff --git a/front/src/main/java/com/hcy/front/vo/order/OrderListVo.java b/front/src/main/java/com/hcy/front/vo/order/OrderListVo.java index 83fff65..0375f15 100644 --- a/front/src/main/java/com/hcy/front/vo/order/OrderListVo.java +++ b/front/src/main/java/com/hcy/front/vo/order/OrderListVo.java @@ -116,4 +116,6 @@ public class OrderListVo implements Serializable { private int contactBtn; private BigDecimal projectCost; //项目费用 + + private int uploadServiceImgBtn; //上传服务图片按钮:0-隐藏;1-显示 } diff --git a/front/src/main/resources/application.yml b/front/src/main/resources/application.yml index 06241c2..3707050 100644 --- a/front/src/main/resources/application.yml +++ b/front/src/main/resources/application.yml @@ -1,7 +1,7 @@ # 项目配置 like: -# upload-directory: /data/file/uploads/ # 文件上传目录 - upload-directory: E:\img\ + upload-directory: /data/file/uploads/ # 文件上传目录 +# upload-directory: E:\img\ # 服务配置 server: port: 8086 @@ -20,16 +20,16 @@ spring: static-path-pattern: /api/static/** # 数据源配置 datasource: - url: jdbc:mysql://192.168.111.98:3306/homemaking_no_staff?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false - type: com.zaxxer.hikari.HikariDataSource # 数据源类型 - driver-class-name: com.mysql.jdbc.Driver # MySql的驱动 - username: root # 数据库账号 - password: 1234 -# url: jdbc:mysql://123.207.77.26:3306/homemaking?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false +# url: jdbc:mysql://192.168.111.98:3306/homemaking_no_staff?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false # type: com.zaxxer.hikari.HikariDataSource # 数据源类型 # driver-class-name: com.mysql.jdbc.Driver # MySql的驱动 -# username: Homemaking # 数据库账号 -# password: kpHaxTyz4ehkYDpS +# username: root # 数据库账号 +# password: 1234 + url: jdbc:mysql://123.207.77.26:3306/homemaking?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false + type: com.zaxxer.hikari.HikariDataSource # 数据源类型 + driver-class-name: com.mysql.jdbc.Driver # MySql的驱动 + username: Homemaking # 数据库账号 + password: kpHaxTyz4ehkYDpS hikari: connection-timeout: 30000 # 等待连接分配连接的最大时长(毫秒),超出时长还没可用连接则发送SQLException,默认30秒 minimum-idle: 5 # 最小连接数