huliguo
2025-07-03 e3a2245265516fef78b4737d6fffc939e7c5e0af
bug修改
17个文件已添加
103个文件已修改
3259 ■■■■ 已修改文件
pt-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/AddressBookController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/AgreementController.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/AppUserController.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/BannerController.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/CommunityController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/CourierController.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/EvaluationController.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/FeedbackController.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/OrderController.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/PhoneController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/ReportController.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/SystemConfigController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/VipOrderController.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/errand/VipSettingController.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/resources/application.yml 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-common/pom.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-common/src/main/java/com/ruoyi/common/utils/OssConfig.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-common/src/main/java/com/ruoyi/common/utils/OssService.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/pom.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/domain/AddressBook.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/domain/Agreement.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/domain/AppUser.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/domain/Order.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/domain/Phone.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/domain/Report.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/domain/VipSetting.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/mapper/CommunityMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/mapper/CourierMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/mapper/VipOrderMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddAddressBookDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddEvaluationDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddFeedbackDTO.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddRegisterReportDTO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddReportDTO.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AgreementDTO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AppletLogin.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/BirthDayDTO.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/ConfirmOrderDTO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/RegisterDTO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/SetConfirmOrderDTO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/AgreementContentDTO.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/BannerPageDTO.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/FinanceStatisticsDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/SetPriceDTO.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AddressBookByCommunityIdVO.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AddressBookListVO.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AppUserInfoVO.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AppUserOrderListVO.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/ConfirmOrderVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/CourierInfoVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/CourierOrderListVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/OrderDetailVO.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/OrderPageVO.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/VipInfoListVO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/login/LoginVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/AppUserPageListVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/BannerDetailVo.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/CourierSysDetailVO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/FeedbackPageListVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/FinanceStatisticsVO.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/AddressBookService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/AppUserService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/CommunityService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/EvaluationService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/FeedbackService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/OrderService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/ReportService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/VipOrderService.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/VipSettingService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/AddressBookServiceImpl.java 69 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/AppUserServiceImpl.java 247 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/CommunityServiceImpl.java 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/CourierServiceImpl.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/EvaluationServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/FeedbackServiceImpl.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/OrderServiceImpl.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/PhoneServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/ReportServiceImpl.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipOrderServiceImpl.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipSettingServiceImpl.java 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/SMSUtil.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/WXCore.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/WeChatUtil.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/sms/AliyunSmsService.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/HttpUtil.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/PayResult.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/RefundCallbackResult.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/WechatPayConfig.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/WechatPayService.java 727 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/XMLUtil.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/cert/apiclient_cert.p12 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/cert/apiclient_cert.pem 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/cert/apiclient_key.pem 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/AddressBookMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/AppUserMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/CommunityMapper.xml 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/CourierMapper.xml 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/EvaluationMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/FeedbackMapper.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/OrderMapper.xml 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/ReportMapper.xml 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-errand/src/main/resources/mapper/VipOrderMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/object/dto/AddDeptDTO.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/object/dto/EditSysRoleDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/resources/mapper/system/SysMenuMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/resources/mapper/system/SysUserMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-system/src/main/resources/mapper/system/SysUserRoleMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pt-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -5,6 +5,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.OssService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
@@ -44,7 +45,7 @@
    /**
     * 通用上传请求(单个)
     */
    @ApiOperation(value = "文件上传", notes = "文件上传")
 /*   @ApiOperation(value = "文件上传", notes = "文件上传")
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) throws Exception {
        try {
@@ -62,8 +63,20 @@
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }*/
    @Autowired
    private OssService ossService;
    @ApiOperation(value = "文件上传", notes = "文件上传")
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) throws Exception {
        // 指定存储目录,例如images
        AjaxResult ajax = AjaxResult.success();
        String directory = "images";
        String url = ossService.uploadFile(file, directory);
        ajax.put("url", url);
//        System.err.println(url);
        return ajax;
    }
    /**
     * 通用上传请求(多个)
     */
pt-admin/src/main/java/com/ruoyi/web/controller/errand/AddressBookController.java
@@ -55,9 +55,8 @@
     */
    @PostMapping("/add")
    @ApiOperation(value = "添加新地址",tags = "app用户端-地址簿")
    public R<Void> add(@RequestBody AddAddressBookDTO addAddressBookDTO ) {
        addressBookService.add(addAddressBookDTO);
        return R.ok();
    public R<Integer> add(@RequestBody AddAddressBookDTO addAddressBookDTO ) {
        return R.ok(addressBookService.add(addAddressBookDTO));
    }
    /**
     * 修改地址
pt-admin/src/main/java/com/ruoyi/web/controller/errand/AgreementController.java
@@ -4,15 +4,23 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.domain.Agreement;
import com.ruoyi.errand.mapper.AgreementMapper;
import com.ruoyi.errand.object.dto.app.AgreementDTO;
import com.ruoyi.errand.object.dto.sys.AgreementContentDTO;
import com.ruoyi.errand.service.AgreementService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.core.Local;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping(value = "/app/agreement")
@@ -21,9 +29,11 @@
    @Autowired
    private AgreementService agreementService;
    @Autowired
    private AgreementMapper agreementMapper;
    /**
     * 协议 类型(1=用户协议,2=隐私协议,3=下单须知,4=注销协议,5=首页介绍,6=快递代拿下单说明,7=商品代买下单说明)
     * 协议 类型(1=用户协议,2=隐私协议,3=下单须知,4=注销协议,5=首页介绍,6=快递代拿下单说明,7=商品代买下单说明,8=会员协议)
     */
    @GetMapping("/getAgreementByType")
    @ApiOperation(value = "根据类型获取不同协议",tags = "app用户端-协议")
@@ -35,16 +45,83 @@
    @PreAuthorize("@ss.hasPermi('system:agreement:list')")
    @ApiOperation(value = "协议管理-添加", tags = {"管理后台-系统管理"})
    public R<Void> addAgreement(@RequestBody AgreementDTO agreementDTO){
        //先删除启动页的数据
        Agreement one = agreementService.getOne(new LambdaQueryWrapper<Agreement>().eq(Agreement::getType, agreementDTO.getType()));
        if (one!=null){
            agreementService.removeById(one);
        }
        Agreement agreement = new Agreement();
        BeanUtils.copyProperties(agreementDTO,agreement);
        agreementService.save(agreement);
        one.setContent(agreementDTO.getContent());
        agreementService.updateById(one);
        return R.ok();
    }
    @PostMapping("/addAgreement/content")
    @PreAuthorize("@ss.hasPermi('system:agreement:list')")
    @ApiOperation(value = "协议管理-内容管理", tags = {"管理后台-系统管理"})
    public R<Void> addAgreementContent(@RequestBody AgreementContentDTO dto){
        //修改
        List<Agreement> agreementList = agreementMapper.selectList(new LambdaQueryWrapper<Agreement>().in(Agreement::getType, Arrays.asList(5, 6, 7)));
        ArrayList<Integer> types = new ArrayList<>();
        types.add(5);
        types.add(6);
        types.add(7);
        if (agreementList!=null&& !agreementList.isEmpty()){
            agreementList.forEach(agreement -> {
                if (agreement.getType()==5){
                    agreement.setContent(dto.getContent());
                    types.remove(agreement.getType());
                    this.agreementMapper.updateById(agreement);
                }
                if (agreement.getType()==6){
                    agreement.setContent(dto.getTakeContent());
                    types.remove(agreement.getType());
                    this.agreementMapper.updateById(agreement);
                }
                if (agreement.getType()==7){
                    agreement.setContent(dto.getBuyContent());
                    types.remove(agreement.getType());
                    this.agreementMapper.updateById(agreement);
                }
            });
        }
       if (!types.isEmpty()){
           types.forEach(type -> {
               if (type==5){
                   Agreement agreement = new Agreement();
                   agreement.setContent(dto.getContent());
                   agreement.setType(type);
                   agreement.setCreateTime(LocalDateTime.now());
                   this.agreementMapper.insert(agreement);
               }
               if (type==6){
                   Agreement agreement = new Agreement();
                   agreement.setContent(dto.getTakeContent());
                   agreement.setType(type);
                   agreement.setCreateTime(LocalDateTime.now());
                   this.agreementMapper.insert(agreement);
               }
               if (type==7){
                   Agreement agreement = new Agreement();
                   agreement.setContent(dto.getBuyContent());
                   agreement.setType(type);
                   agreement.setCreateTime(LocalDateTime.now());
                   this.agreementMapper.insert(agreement);
               }
           });
       }
       return R.ok();
    }
    @GetMapping("/getAgreement/content")
    @PreAuthorize("@ss.hasPermi('system:agreement:list')")
    @ApiOperation(value = "协议管理-内容管理-查看详情", tags = {"管理后台-系统管理"})
    public R<AgreementContentDTO> getAgreementContent(){
        AgreementContentDTO vo = new AgreementContentDTO();
        List<Agreement> agreementList = agreementMapper.selectList(new LambdaQueryWrapper<Agreement>().in(Agreement::getType, Arrays.asList(5, 6, 7)));
        if (agreementList!=null&& !agreementList.isEmpty()){
            agreementList.forEach(agreement -> {
                if (agreement.getType()==5) vo.setContent(agreement.getContent());
                if (agreement.getType()==6) vo.setTakeContent(agreement.getContent());
                if (agreement.getType()==7) vo.setBuyContent(agreement.getContent());
            });
        }
        return R.ok(vo);
    }
}
pt-admin/src/main/java/com/ruoyi/web/controller/errand/AppUserController.java
@@ -95,9 +95,9 @@
     */
    @PostMapping("/register")
    @ApiOperation(value = "注册",tags = "app用户端")
    public R<Void> register(@RequestBody @Valid RegisterDTO registerDTO) {
        appUserService.register(registerDTO);
        return R.ok();
    public R<LoginVO> register(@RequestBody @Valid RegisterDTO registerDTO) {
        return R.ok( appUserService.register(registerDTO));
    }
    /**
     * 根据小区id(可选择)
@@ -128,6 +128,24 @@
        return R.ok();
    }
    /**
     * 修改姓名
     */
    @PutMapping("/setName")
    @ApiOperation(value = "修改姓名",tags = "app用户端-个人信息")
    public R<Void> setName(@RequestParam String name) {
        appUserService.setName(name);
        return R.ok();
    }
    /**
     * 修改头像
     */
    @PutMapping("/setAvatar")
    @ApiOperation(value = "修改头像",tags = "app用户端-个人信息")
    public R<Void> setAvatar(@RequestParam String avatar) {
        appUserService.setAvatar(avatar);
        return R.ok();
    }
    /**
     * 修改生日
     */
    @PutMapping("/setBirthDay")
@@ -142,8 +160,8 @@
     */
    @DeleteMapping("/delete")
    @ApiOperation(value = "注销账号",tags = "app用户端-个人信息")
    public R<Void> delete() {
        appUserService.delete();
    public R<Void> delete(@RequestHeader("Authorization") String token) {
        appUserService.delete(token);
        return R.ok();
    }
@@ -263,7 +281,7 @@
    @GetMapping("/detail")
    @PreAuthorize("@ss.hasPermi('system:appuser:list')")
    @ApiOperation(value = "用户管理-用户详情", tags = "系统后台-用户管理")
    public R<AppUserSysDetailVO> detail(@RequestParam("id") Integer id) {
    public R<AppUserSysDetailVO> detail(@RequestParam("id") String id) {
        return R.ok(appUserService.detail(id));
    }
    /**
@@ -272,7 +290,7 @@
    @PutMapping("/froze")
    @PreAuthorize("@ss.hasPermi('system:appuser:list')")
    @ApiOperation(value = "用户管理-冻结/解冻", tags = "系统后台-用户管理")
    public R froze(@RequestParam("id") Integer id) {
    public R froze(@RequestParam("id") String id) {
        appUserService.froze(id);
        return R.ok();
    }
@@ -282,7 +300,7 @@
    @GetMapping("/refund")
    @PreAuthorize("@ss.hasPermi('system:appuser:list')")
    @ApiOperation(value = "用户管理-会员退费", tags = "系统后台-用户管理")
    public R<Void> refund(@RequestParam("id") Integer id) {
    public R<Void> refund(@RequestParam("id") String id) {
        appUserService.refund(id);
        return R.ok();
    }
@@ -290,26 +308,18 @@
    /**
     * 订单取消支付回退
     *
     * @param refundCallbackResult
     * @param response
     * @return
     */
    @ResponseBody
    @GetMapping("/refundPayMoneyCallback")
    public void refundPayMoneyCallback(RefundCallbackResult refundCallbackResult, HttpServletResponse response) {
        R callback = appUserService.refundPayMoneyCallback(refundCallbackResult);
    @PostMapping("/refundPayMoneyCallback")
    public String refundPayMoneyCallback(@RequestBody(required = false) String xmlData) {
        System.out.println("会员退费:" + xmlData);
        R callback = appUserService.refundPayMoneyCallback(xmlData);
        if (callback.getCode() == 200) {
            response.setStatus(200);
            PrintWriter out = null;
            try {
                out = response.getWriter();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            out.println("success");
            out.flush();
            out.close();
            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        }else {
            System.err.println("支付回退错误:"+callback.getMsg());
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }
    }
pt-admin/src/main/java/com/ruoyi/web/controller/errand/BannerController.java
@@ -5,6 +5,7 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.domain.Banner;
import com.ruoyi.errand.object.dto.sys.AddBannerDTO;
import com.ruoyi.errand.object.dto.sys.BannerPageDTO;
import com.ruoyi.errand.object.dto.sys.OrderPageListDTO;
import com.ruoyi.errand.object.vo.app.BannerVO;
import com.ruoyi.errand.object.vo.sys.BannerDetailVo;
@@ -42,14 +43,12 @@
    /**
     * 分页查询
     */
    @GetMapping("/list")
    @PostMapping("/list")
    @PreAuthorize("@ss.hasPermi('system:banner:list')")
    @ApiOperation(value = "banner管理-分页查询", tags = {"管理后台-系统管理"})
    public R<IPage<BannerPageListVO>> pageList(@RequestParam("pageNum") Integer pageNum,
                                              @RequestParam("pageSize") Integer pageSize,
                                              @RequestParam("name") String name) {
        IPage<BannerPageListVO> iPage=new Page<>(pageNum,pageSize);
        return R.ok(bannerService.pageList(iPage,name));
    public R<IPage<BannerPageListVO>> pageList(@RequestBody BannerPageDTO dto) {
        IPage<BannerPageListVO> iPage=new Page<>(dto.getPageNum(),dto.getPageSize());
        return R.ok(bannerService.pageList(iPage,dto.getName()));
    }
    /**
@@ -67,7 +66,7 @@
     */
    @PutMapping("/edit")
    @PreAuthorize("@ss.hasPermi('system:banner:list')")
    @ApiOperation(value = "banner管理-添加", tags = {"管理后台-系统管理"})
    @ApiOperation(value = "banner管理-编辑", tags = {"管理后台-系统管理"})
    public R edit(@RequestBody EditBannerDTO editBannerDTO) {
        bannerService.edit(editBannerDTO);
        return R.ok();
pt-admin/src/main/java/com/ruoyi/web/controller/errand/CommunityController.java
@@ -43,8 +43,8 @@
    @GetMapping("/getTotalCommunityList")
    @PreAuthorize("@ss.hasPermi('system:index:statistics')")
    @ApiOperation(value = "获取所有小区列表(开通的小区总数取列表大小吧)",tags = "系统后台-首页")
    public R<List<CommunityListVO>> getTotalCommunityList() {
        return communityService.getTotalCommunityList();
    public R<List<CommunityListVO>> getTotalCommunityList(@RequestParam(value = "name",required = false) String name) {
        return communityService.getTotalCommunityList(name);
    }
    /**
pt-admin/src/main/java/com/ruoyi/web/controller/errand/CourierController.java
@@ -82,7 +82,7 @@
    }
    /**
     * 加载未绑定小区的跑腿员   权限设置
     * 加载未绑定小区的跑腿员
     */
    @GetMapping("/getAllCourierList")
    @PreAuthorize("@ss.hasPermi('system:appuser:list')")
@@ -92,7 +92,7 @@
    }
    /**
     * 跑腿员管理列表 权限设置
     * 跑腿员管理列表
     */
    @PostMapping("/list")
    @PreAuthorize("@ss.hasPermi('system:courier:list')")
@@ -101,7 +101,7 @@
        return R.ok(courierService.getCourierPageList(courierPageListDTO));
    }
    /**
     * 查看详情 权限设置
     * 查看详情
     */
    @GetMapping("/detail")
    @PreAuthorize("@ss.hasPermi('system:courier:list')")
@@ -110,7 +110,7 @@
        return R.ok(courierService.detail(id));
    }
    /**
     * 添加 权限设置
     * 添加
     */
    @PostMapping("/add")
    @PreAuthorize("@ss.hasPermi('system:courier:list')")
@@ -120,7 +120,7 @@
        return R.ok();
    }
    /**
     * 编辑 权限设置
     * 编辑
     */
    @PutMapping("/edit")
    @PreAuthorize("@ss.hasPermi('system:courier:list')")
@@ -131,7 +131,7 @@
    }
    /**
     * 删除 权限设置
     * 删除
     */
    @DeleteMapping("/delete")
    @PreAuthorize("@ss.hasPermi('system:courier:list')")
@@ -141,7 +141,7 @@
        return R.ok();
    }
    /**
     * 复职/离职 权限设置
     * 复职/离职
     */
    @PutMapping("/froze")
    @PreAuthorize("@ss.hasPermi('system:courier:list')")
pt-admin/src/main/java/com/ruoyi/web/controller/errand/EvaluationController.java
@@ -27,9 +27,14 @@
     * 订单评价
     */
    @PostMapping("/add")
    @ApiOperation(value = "评价订单",tags = "app用户端-订单")
    @ApiOperation(value = "评价订单",tags = {"app用户端-订单","app跑腿员-订单"})
    public R<Void> add(@RequestBody @Valid AddEvaluationDTO addEvaluationDTO) {
        evaluationService.add(addEvaluationDTO);
        if(addEvaluationDTO.getEvaluationId()==null){
            evaluationService.add(addEvaluationDTO);
        }else {
            evaluationService.edit(addEvaluationDTO);
        }
        return R.ok();
    }
}    
pt-admin/src/main/java/com/ruoyi/web/controller/errand/FeedbackController.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.object.dto.app.AddFeedbackDTO;
import com.ruoyi.errand.object.dto.sys.FeedbackPageListDTO;
import com.ruoyi.errand.object.dto.sys.OrderPageListDTO;
import com.ruoyi.errand.object.vo.sys.FeedbackPageListVO;
@@ -31,8 +32,8 @@
     */
    @PostMapping("/add")
    @ApiOperation(value = "意见反馈",tags = "app用户端-意见反馈")
    public R<Integer> add(@RequestParam String content) {
        feedbackService.add(content);
    public R add(@RequestBody AddFeedbackDTO dto) {
        feedbackService.add(dto);
        return R.ok();
    }
@@ -42,7 +43,7 @@
     */
    @PostMapping("/list")
    @PreAuthorize("@ss.hasPermi('system:feedback:list')")
    @ApiOperation(value = "反馈管理-分页列表", tags = "系统后台-订单管理")
    @ApiOperation(value = "反馈管理-分页列表", tags = "系统后台-意见反馈")
    public R<IPage<FeedbackPageListVO>> getFeedbackPageList(@RequestBody @Valid FeedbackPageListDTO feedbackPageListDTO) {
        return R.ok(feedbackService.getFeedbackPageList(feedbackPageListDTO));
    }
@@ -51,7 +52,7 @@
     */
    @DeleteMapping("/delete")
    @PreAuthorize("@ss.hasPermi('system:feedback:list')")
    @ApiOperation(value = "反馈管理-删除", tags = "系统后台-订单管理")
    @ApiOperation(value = "反馈管理-删除", tags = "系统后台-意见反馈")
    public R delete(@RequestParam("id")Integer id) {
        feedbackService.delete(id);
        return R.ok();
@@ -62,7 +63,7 @@
     */
    @PutMapping("/dispose")
    @PreAuthorize("@ss.hasPermi('system:feedback:list')")
    @ApiOperation(value = "反馈管理-处理", tags = "系统后台-订单管理")
    @ApiOperation(value = "反馈管理-处理", tags = "系统后台-意见反馈")
    public R dispose(@RequestParam("id")Integer id) {
        feedbackService.dispose(id);
        return R.ok();
pt-admin/src/main/java/com/ruoyi/web/controller/errand/OrderController.java
@@ -19,8 +19,11 @@
import com.ruoyi.errand.object.vo.sys.OrderSysDetailVO;
import com.ruoyi.errand.object.vo.sys.UserStatsVO;
import com.ruoyi.errand.service.OrderService;
import com.ruoyi.errand.service.VipOrderService;
import com.ruoyi.errand.utils.RefundCallbackResult;
import com.ruoyi.errand.utils.UniPayCallbackResult;
import com.ruoyi.errand.utils.wx.PayResult;
import com.ruoyi.errand.utils.wx.WechatPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@@ -29,6 +32,7 @@
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
@@ -44,6 +48,11 @@
public class OrderController {
    @Autowired
    private OrderService orderService;
    @Autowired
    private WechatPayService wechatPayService;
    @Autowired
    private VipOrderService vipOrderService;
    /**
     * 下单
@@ -67,12 +76,18 @@
     * 订单支付回调通知
     */
    @ResponseBody
    @GetMapping("/orderPaymentCallback")
    public void orderPaymentCallback(UniPayCallbackResult uniPayCallbackResult, HttpServletResponse response){
        String jsonString = JSONObject.toJSONString(uniPayCallbackResult);
        log.info("订单支付回调json:{}", jsonString);
        R callback = orderService.orderPaymentCallback(uniPayCallbackResult);
        if(callback.getCode() == 200){
    @PostMapping("/orderPaymentCallback")
    public void orderPaymentCallback(HttpServletRequest request, HttpServletResponse response){
        System.err.println("11111111111");
        PayResult payResult= null;
        try {
            payResult = wechatPayService.processNotify(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println("1111111111111111111111");
        R callback = orderService.orderPaymentCallback(payResult);
        if(callback.getCode() == 200) {
            response.setStatus(200);
            PrintWriter out = null;
            try {
@@ -93,8 +108,8 @@
    @GetMapping("/getAppUserOrderList")
    @ApiOperation(value = "订单列表",tags = "app用户端-订单页面")
    public R<IPage<AppUserOrderListVO>> getAppUserOrderList(
            @RequestParam(value = "pageNum",defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize",defaultValue = "10") Integer pageSize,
            @RequestParam(value = "pageNum",defaultValue = "1",required = false) Integer pageNum,
            @RequestParam(value = "pageSize",defaultValue = "10",required = false) Integer pageSize,
            @RequestParam(value = "orderStatus",required = false) Integer orderStatus) {
        return R.ok(orderService.getAppUserOrderList(pageNum,pageSize,orderStatus));
    }
@@ -129,26 +144,16 @@
    /**
     * 订单取消支付回退
     *
     * @param refundCallbackResult
     * @param response
     * @return
     */
    @ResponseBody
    @GetMapping("/refundPayMoneyCallback")
    public void refundPayMoneyCallback(RefundCallbackResult refundCallbackResult, HttpServletResponse response) {
        R callback = orderService.refundPayMoneyCallback(refundCallbackResult);
    public String refundPayMoneyCallback( @RequestBody(required = false) String xmlData) {
        R callback = orderService.refundPayMoneyCallback(xmlData);
        if (callback.getCode() == 200) {
            response.setStatus(200);
            PrintWriter out = null;
            try {
                out = response.getWriter();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            out.println("success");
            out.flush();
            out.close();
            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        }else {
            System.err.println("支付回退错误:"+callback.getMsg());
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }
    }
    /**
@@ -281,8 +286,13 @@
    @GetMapping("/detail")
    @PreAuthorize("@ss.hasPermi('system:order:list')")
    @ApiOperation(value = "订单管理-订单详情", tags = "系统后台-订单管理")
    public R<OrderSysDetailVO> detail(@RequestParam("id") Integer id) {
        return R.ok(orderService.detail(id));
    public R<OrderSysDetailVO> detail(@RequestParam("id") Integer id,@RequestParam("type") Integer type) {
        if (type==2){
            return R.ok(orderService.detail(id));
        }else {
            return R.ok(vipOrderService.detail(id));
        }
    }
    /**
pt-admin/src/main/java/com/ruoyi/web/controller/errand/PhoneController.java
@@ -1,6 +1,8 @@
package com.ruoyi.web.controller.errand;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.domain.Phone;
import com.ruoyi.errand.object.vo.app.ConfirmOrderVO;
import com.ruoyi.errand.service.PhoneService;
import io.swagger.annotations.Api;
@@ -24,7 +26,7 @@
     * 联系客服
     */
    @GetMapping("/getServletPhone")
    @ApiOperation(value = "获取客服电话",tags = "app用户端-联系客服")
    @ApiOperation(value = "获取客服电话",tags = { "app用户端-联系客服" })
    public R<String> getServletPhone() {
        return R.ok(phoneService.getServletPhone());
    }
@@ -39,4 +41,20 @@
        phoneService.saveServicePhone(phone);
        return R.ok();
    }
    /**
     * 联系客服
     */
    @GetMapping("/getSysPhone")
    @PreAuthorize("@ss.hasPermi('system:feedback:list')")
    @ApiOperation(value = "获取客服电话",tags = { "管理后台-系统管理" })
    public R<String> getSysPhone() {
        Phone one = phoneService.getOne(new LambdaQueryWrapper<Phone>().eq(Phone::getType, 1));
        if (one != null) {
            return R.ok(one.getPhone());
        }else {
            return R.ok();
        }
    }
}    
pt-admin/src/main/java/com/ruoyi/web/controller/errand/ReportController.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.domain.Report;
import com.ruoyi.errand.object.dto.app.AddRegisterReportDTO;
import com.ruoyi.errand.object.dto.app.AddReportDTO;
import com.ruoyi.errand.object.dto.sys.CourierPageListDTO;
import com.ruoyi.errand.object.dto.sys.ReportPageListDTO;
@@ -40,20 +41,20 @@
    }
    /**
     * 未开通上报列表 权限设置
     * 未开通上报列表
     */
    @PostMapping("/list")
    @PreAuthorize("@ss.hasPermi('system:community:list')")
    @PreAuthorize("@ss.hasPermi('system:report:list')")
    @ApiOperation(value = "未开通上报管理-列表", tags = "系统后台-小区管理")
    public R<IPage<ReportPageListVO>> getReportList(@RequestBody @Valid ReportPageListDTO reportPageListDTO) {
        return R.ok(reportService.getReportList(reportPageListDTO));
    }
    /**
     * 处理  权限设置
     * 处理
     */
    @PutMapping("/dispose")
    @PreAuthorize("@ss.hasPermi('system:community:list')")
    @PreAuthorize("@ss.hasPermi('system:report:list')")
    @ApiOperation(value = "未开通上报管理-处理", tags = "系统后台-小区管理")
    public R<Void> dispose(@RequestParam("id")Integer id) {
        reportService.dispose(id);
@@ -61,10 +62,10 @@
    }
    /**
     * 删除 权限设置
     * 删除
     */
    @DeleteMapping("/delete")
    @PreAuthorize("@ss.hasPermi('system:community:list')")
    @PreAuthorize("@ss.hasPermi('system:report:list')")
    @ApiOperation(value = "未开通上报管理-删除", tags = "系统后台-小区管理")
    public R<Void> delete(@RequestParam("id")Integer id) {
        reportService.delete(id);
pt-admin/src/main/java/com/ruoyi/web/controller/errand/SystemConfigController.java
@@ -2,6 +2,7 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.constant.SystemConfigTypeConstant;
import com.ruoyi.errand.domain.SystemConfig;
@@ -46,7 +47,7 @@
    @GetMapping("/index/start")
    @ApiOperation(value = "启动页-详情", tags = {"app用户端-启动页","管理后台-启动页配置"})
    public R<StartPageSetDto> indexStart(){
        SystemConfig one = systemConfigService.lambdaQuery().eq(SystemConfig::getType, SystemConfigTypeConstant.START_PAGE).one();
        SystemConfig one = systemConfigService.getBaseMapper().selectOne(new LambdaQueryWrapper<SystemConfig>().eq(SystemConfig::getType, SystemConfigTypeConstant.START_PAGE));;
        if (one==null){
            return R.ok();
        }
pt-admin/src/main/java/com/ruoyi/web/controller/errand/VipOrderController.java
@@ -5,12 +5,15 @@
import com.ruoyi.errand.object.dto.app.VipPaymentDTO;
import com.ruoyi.errand.service.VipOrderService;
import com.ruoyi.errand.utils.UniPayCallbackResult;
import com.ruoyi.errand.utils.wx.PayResult;
import com.ruoyi.errand.utils.wx.WechatPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
@@ -23,6 +26,9 @@
public class VipOrderController {
    @Autowired
    private VipOrderService vipOrderService;
    @Autowired
    private WechatPayService wechatPayService;
    /**
@@ -39,11 +45,18 @@
     * 订单支付回调通知
     */
    @ResponseBody
    @GetMapping("/orderPaymentCallback")
    public void orderPaymentCallback(UniPayCallbackResult uniPayCallbackResult, HttpServletResponse response){
        String jsonString = JSONObject.toJSONString(uniPayCallbackResult);
        log.info("订单支付回调json:{}", jsonString);
        R callback = vipOrderService.orderPaymentCallback(uniPayCallbackResult);
    @PostMapping("/orderPaymentCallback")
    public void orderPaymentCallback(HttpServletRequest request, HttpServletResponse response){
        System.err.println("1111111111111");
        PayResult payResult= null;
        try {
            payResult = wechatPayService.processNotify(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println("1111111111111111111111");
//        System.out.println(jsonString);
        R callback = vipOrderService.orderPaymentCallback(payResult);
        if(callback.getCode() == 200){
            response.setStatus(200);
            PrintWriter out = null;
pt-admin/src/main/java/com/ruoyi/web/controller/errand/VipSettingController.java
@@ -40,7 +40,7 @@
     */
    @PostMapping("/setPrice")
    @PreAuthorize("@ss.hasPermi('system:vip:list')")
    @ApiOperation(value = "会员管理-设置价格", tags = "系统后台-订单管理")
    @ApiOperation(value = "会员管理-设置价格", tags = "系统后台-会员管理")
    public R setPrice(@RequestBody @Valid SetPriceDTO setPriceDTO) {
        vipSettingService.setPrice(setPriceDTO);
        return R.ok();
@@ -49,9 +49,20 @@
    /**
     * 查看详情
     */
    @PostMapping("/getPrice")
    @PreAuthorize("@ss.hasPermi('system:vip:list')")
    @ApiOperation(value = "会员管理-获取会员配置", tags = "系统后台-会员管理")
    public R<SetPriceDTO> getPrice() {
        return R.ok(vipSettingService.getPrice());
    }
    /**
     * 查看详情
     */
    @GetMapping("/getVipList")
    @PreAuthorize("@ss.hasPermi('system:vip:list')")
    @ApiOperation(value = "会员管理-列表", tags = "系统后台-订单管理")
    @ApiOperation(value = "会员管理-列表", tags = "系统后台-会员管理")
    public R<List<VipInfoListVO>> getVipList() {
        return R.ok(vipSettingService.getVipInfoList());
    }
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
@@ -8,6 +8,7 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.errand.object.dto.sys.FinanceStatisticsDTO;
import com.ruoyi.errand.object.vo.sys.FinanceStatisticsVO;
import com.ruoyi.system.object.dto.AddDeptDTO;
import com.ruoyi.system.object.vo.SysDeptPageVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
@@ -94,9 +95,9 @@
    @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "部门管理-新增部门", tags = "系统后台-权限管理")
    @GetMapping("/add")
    public AjaxResult add(@RequestParam("name")String name) {
        deptService.add(name);
    @PostMapping("/add")
    public AjaxResult add(@RequestBody AddDeptDTO dto) {
        deptService.add(dto.getName());
        return success();
    }
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -1,8 +1,11 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.ruoyi.system.mapper.SysMenuMapper;
import com.ruoyi.system.object.dto.SetPasswordDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -43,6 +46,8 @@
    private SysPermissionService permissionService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    /**
     * 登录方法
@@ -79,20 +84,36 @@
    public AjaxResult getInfo() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        if (!loginUser.getPermissions().equals(permissions)) {
            loginUser.setPermissions(permissions);
            tokenService.refreshToken(loginUser);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("permissions" ,getUserPaths(user.getUserId()));
        return ajax;
    }
    /**
     * 获取用户拥有的所有path
     * @param userId 用户ID
     * @return 用户拥有的所有path列表
     */
    public List<String> getUserPaths(Long userId) {
        List<Long> ids = new ArrayList<>();
        // 根据用户id查询出menus
        List<SysMenu> menus = sysMenuMapper.selectMenusByUserId(userId);
        //将id和父类id取出
        menus.forEach(menu -> {
            ids.add(menu.getMenuId());
            if (null!= menu.getParentId() && menu.getParentId() != 0) {
                ids.add(menu.getParentId());
            }
        });
        if (menus.isEmpty()) {
            return Collections.emptyList();
        }
        return sysMenuMapper.getPathsByMenuIds(ids);
    }
    /**
     * 获取路由信息
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
@@ -1,6 +1,9 @@
package com.ruoyi.web.controller.system;
import java.util.Map;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -37,6 +40,8 @@
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysUserMapper sysUserMapper;
    /**
     * 个人信息
@@ -81,27 +86,24 @@
     * 重置密码
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/updatePwd")
    @PostMapping("/updatePwd")
    public AjaxResult updatePwd(@RequestBody Map<String, String> params) {
        String oldPassword = params.get("oldPassword");
        String newPassword = params.get("newPassword");
        LoginUser loginUser = getLoginUser();
        String userName = loginUser.getUsername();
        String password = loginUser.getPassword();
        if (!SecurityUtils.matchesPassword(oldPassword, password)) {
        String userName = params.get("username");
        SysUser sysUser = sysUserMapper.selectUserByUserName(userName);
        if (sysUser.getStatus().equals("1")){
            throw new ServiceException("该用户已被冻结");
        }
        if (!SecurityUtils.matchesPassword(oldPassword, sysUser.getPassword())) {
            return error("修改密码失败,旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, password)) {
        if (SecurityUtils.matchesPassword(newPassword, sysUser.getPassword())) {
            return error("新密码不能与旧密码相同");
        }
        newPassword = SecurityUtils.encryptPassword(newPassword);
        if (userService.resetUserPwd(userName, newPassword) > 0) {
            // 更新缓存用户密码
            loginUser.getUser().setPassword(newPassword);
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改密码异常,请联系管理员");
        userService.resetUserPwd(userName, newPassword);
        return success();
    }
    /**
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -77,7 +77,7 @@
    @ApiOperation(value = "角色管理-分页列表", tags = "系统后台-权限管理")
    public R<IPage<SysRolePageVO>> page(@RequestParam(value = "pageNum",defaultValue = "0")Integer pageNum,
                                        @RequestParam(value = "pageSize",defaultValue="10")Integer pageSize,
                                        @RequestParam(value = "name",required = false)String name) {
                                        @RequestParam(value = "roleName",required = false)String name) {
        IPage<SysRolePageVO> iPage = new Page<>(pageNum, pageSize);
        return R.ok(roleService.page(iPage,name));
    }
@@ -142,11 +142,14 @@
    @Log(title = "角色管理", businessType = BusinessType.INSERT)
    @PutMapping("/edit")
    public R<Void> edit(@Valid @RequestBody EditSysRoleDTO dto) {
        if (dto.getRoleId()==2){
            return R.fail("超级管理员不能修改");
        }
        roleService.edit(dto);
        // 更新缓存用户权限
        LoginUser loginUser = getLoginUser();
        if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) {
            loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
            loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getPhonenumber()));
            loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
            tokenService.setLoginUser(loginUser);
        }
@@ -213,6 +216,9 @@
    @Log(title = "角色管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{roleId}")
    public R<Void> remove(@PathVariable Long roleId) {
        if (roleId==2){
            return R.fail("超级管理员不能删除");
        }
        roleService.deleteRoleById(roleId);
        return R.ok();
    }
pt-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -68,11 +68,11 @@
    @ApiOperation(value = "账号管理-获取账号分页列表", tags = "系统后台-权限管理")
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public R<IPage<SysUserPageListVO>> getSysUserPageList(@RequestParam("pageNum")Integer pageNum,
                                                          @RequestParam("pageSize")Integer pageSize,
                                                          @RequestParam("nickName")String nickName,
                                                          @RequestParam("phone")Integer phone,
                                                          @RequestParam("status")String status) {
    public R<IPage<SysUserPageListVO>> getSysUserPageList(@RequestParam(value = "pageNum",required = false,defaultValue = "0")Integer pageNum,
                                                          @RequestParam(value = "pageSize",required = false,defaultValue = "10")Integer pageSize,
                                                          @RequestParam(value = "nickName",required = false)String nickName,
                                                          @RequestParam(value = "phonenumber",required = false)Integer phone,
                                                          @RequestParam(value = "status",required = false)String status) {
        IPage<SysUserPageListVO> page=new Page<>(pageNum,pageSize);
        return R.ok(userService.getSysUserPageList(page,nickName,phone,status));
    }
@@ -117,7 +117,7 @@
    /**
     * 新增用户
     */
    @ApiOperation(value = "账号管理-查看详情(回显)", tags = "系统后台-权限管理")
    @ApiOperation(value = "账号管理-新增", tags = "系统后台-权限管理")
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping("/add")
pt-admin/src/main/resources/application.yml
@@ -16,7 +16,7 @@
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8084
  port: 8086
  servlet:
    # 应用的访问路径
    context-path: /
@@ -88,7 +88,13 @@
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
        time-between-eviction-runs:
aliyun:
  oss:
    endpoint: oss-cn-chengdu.aliyuncs.com
    access-key-id: LTAI5tRtwxPMw8aohbLLcjjo       # 你的AccessKey ID
    access-key-secret: NSKeley8OjCsl7AQJnDKxPIh1dIaOu # 你的AccessKey Secret
    bucket-name: weiersusong                     # 你的存储空间名称
    domain: weiersusong.oss-cn-chengdu.aliyuncs.com # 访问域名
# token配置
token:
  # 令牌自定义标识
@@ -139,9 +145,18 @@
  # 匹配链接
  urlPatterns: /system/*,/monitor/*,/tool/*
wx:
  appletsAppid: wxedd7aefdfaf897cf
  appid: wxedd7aefdfaf897cf
  appletsAppSecret: e1a8dba539294da6b935e8f0f3b09aac
  mchId: 1719862902
  key: 5Kb8zX9qR2TdF7Yw3vHnJgLp6sA4cE1M
  callbackPath: http://221.182.45.100:8086
  certPath: classpath:cert/apiclient_cert.p12
  RASPath:
ali:
  accessKeyId: LTAI5tRtwxPMw8aohbLLcjjo
  accessKeySecret: NSKeley8OjCsl7AQJnDKxPIh1dIaOu
  signName: 玮儿科技
  templateCode: SMS_319401491
  # 不校验白名单
weapp:
  security:
@@ -202,8 +217,14 @@
      - /app/banner/delete
      - /app/banner/detail
      - /app/phone/saveServicePhone
      - /app/phone/getSysPhone
      - /app/vipSetting/setPrice
      - /app/vipSetting/getVipList
      - /app/vipSetting/getPrice
      - /app/feedback/list
      - /app/feedback/delete
      - /app/feedback/dispose
      - /app/feedback/dispose
      - /app/report/add
      - /app/agreement/addAgreement/content
      - /app/agreement/getAgreement/content
      - /app/user/refundPayMoneyCallback
pt-common/pom.xml
@@ -177,7 +177,11 @@
            <artifactId>easypoi-annotation</artifactId>
            <version>4.4.0</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.15.1</version>
        </dependency>
    </dependencies>
</project>
pt-common/src/main/java/com/ruoyi/common/utils/OssConfig.java
New file
@@ -0,0 +1,25 @@
package com.ruoyi.common.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OssConfig {
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.access-key-id}")
    private String accessKeyId;
    @Value("${aliyun.oss.access-key-secret}")
    private String accessKeySecret;
    @Bean(destroyMethod = "shutdown")
    public OSS ossClient() {
        return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
}
pt-common/src/main/java/com/ruoyi/common/utils/OssService.java
New file
@@ -0,0 +1,73 @@
package com.ruoyi.common.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.PutObjectRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;
@Service
public class OssService {
    @Autowired
    private OSS ossClient;
    @Value("${aliyun.oss.bucket-name}")
    private String bucketName;
    @Value("${aliyun.oss.domain}")
    private String domain;
    /**
     * 上传文件到OSS
     * @param file 上传的文件
     * @param directory 存储目录
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file, String directory) {
        if (file == null || file.isEmpty()) {
            return null;
        }
        try {
            // 生成唯一文件名,避免重复
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = UUID.randomUUID().toString() + fileExtension;
            // 构建完整路径:目录/文件名
            String objectName = directory + "/" + fileName;
            // 上传文件
            ossClient.putObject(new PutObjectRequest(bucketName, objectName, file.getInputStream()));
            // 返回文件URL
            return "https://" + domain + "/" + objectName;
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("文件上传失败");
        } finally {
            // 关闭OSSClient
//            ossClient.shutdown();
        }
    }
    /**
     * 从OSS删除文件
     * @param objectName 文件路径
     */
    public void deleteFile(String objectName) {
        try {
            ossClient.deleteObject(bucketName, objectName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件删除失败");
        } finally {
//            ossClient.shutdown();
        }
    }
}
pt-errand/pom.xml
@@ -43,6 +43,31 @@
            <groupId>com.pt</groupId>
            <artifactId>pt-system</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.5.3</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-http</artifactId>
            <version>5.8.25</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
    </dependencies>
</project>
pt-errand/src/main/java/com/ruoyi/errand/domain/AddressBook.java
@@ -21,7 +21,7 @@
    @ApiModelProperty("用户ID")
    @TableField("app_user_id")
    private Long app_user_id;
    private Long appUserId;
    @ApiModelProperty("收件人姓名")
    @TableField("recipient_name")
@@ -41,19 +41,23 @@
    @ApiModelProperty("是否默认地址:0-否,1-是")
    @TableField("is_default")
    private Integer is_default;
    private Integer isDefault;
    @ApiModelProperty("添加时间")
    @TableField("create_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime create_time;
    private LocalDateTime createTime;
    @ApiModelProperty("更新时间")
    @TableField("update_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime update_time;
    private LocalDateTime updateTime;
    @ApiModelProperty("是否删除:0-否,1-是")
    @TableField("del_flag")
    private Integer del_flag;
    private Integer delFlag;
    @ApiModelProperty("地址扩展字段")
    @TableField("region_extend")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/domain/Agreement.java
@@ -29,5 +29,5 @@
    @ApiModelProperty("添加时间")
    @TableField("create_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime create_time;
    private LocalDateTime createTime;
}
pt-errand/src/main/java/com/ruoyi/errand/domain/AppUser.java
@@ -10,6 +10,7 @@
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Data
@TableName("t_app_user")
@@ -46,7 +47,7 @@
    @ApiModelProperty("生日")
    @TableField("birthday")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate birthday;
    private Date birthday;
    @ApiModelProperty("微信openid")
    @TableField("wx_openid")
@@ -95,4 +96,8 @@
    @TableField("last_login_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime lastLoginTime;
    @ApiModelProperty("地址扩展")
    @TableField("region_extend")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/domain/Order.java
@@ -59,7 +59,7 @@
    @ApiModelProperty("货品件数")
    @TableField("num")
    private Integer num;
    private String num;
    @ApiModelProperty("备注")
    @TableField("remark")
pt-errand/src/main/java/com/ruoyi/errand/domain/Phone.java
@@ -23,7 +23,7 @@
    @ApiModelProperty("小区id")
    @TableField("community_id")
    private Integer community_id;
    private Integer communityId;
    @ApiModelProperty("联系电话")
    @TableField("phone")
pt-errand/src/main/java/com/ruoyi/errand/domain/Report.java
@@ -23,9 +23,13 @@
    @TableField("region_id")
    private Integer regionId;
    @ApiModelProperty("用户ID")
    @TableField("app_user_id")
    private Long appUserId;
    @ApiModelProperty("用户名")
    @TableField("username")
    private String username;
    @ApiModelProperty("用户手机号")
    @TableField("phone")
    private String phone;
    @ApiModelProperty("小区名称")
    @TableField("community_name")
pt-errand/src/main/java/com/ruoyi/errand/domain/VipSetting.java
@@ -21,19 +21,19 @@
    @ApiModelProperty("会员名称")
    @TableField("vip_name")
    private String vip_name;
    private String vipName;
    @ApiModelProperty("会员价格")
    @TableField("vip_price")
    private BigDecimal vip_price;
    private BigDecimal vipPrice;
    @ApiModelProperty("添加时间")
    @TableField("create_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime create_time;
    private LocalDateTime createTime;
    @ApiModelProperty("添加时间")
    @TableField("update_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime update_time;
    private LocalDateTime updateTime;
}
pt-errand/src/main/java/com/ruoyi/errand/mapper/CommunityMapper.java
@@ -18,7 +18,7 @@
public interface CommunityMapper extends BaseMapper<Community> {
    List<CommunityListVO> selectListByRegionId(@Param("regionId") Integer regionId);
    List<CommunityListVO> getTotalCommunityList();
    List<CommunityListVO> getTotalCommunityList(@Param("name") String name);
    List<AllCommunityListVO> getAllCommunityList(@Param("list")List<Integer> list);
pt-errand/src/main/java/com/ruoyi/errand/mapper/CourierMapper.java
@@ -21,7 +21,7 @@
    CourierStatisticsVO getDatStatistics(Integer courierId);
    IPage<CourierOrderListVO> getCourierOrderList(@Param("page") IPage<CourierOrderListVO> page, @Param("orderStatus") Integer orderStatus,@Param("courierId")  Integer courierId);
    IPage<CourierOrderListVO> getCourierOrderList(@Param("page") IPage<CourierOrderListVO> page, @Param("courierId")  Integer courierId ,@Param("orderStatus") Integer orderStatus,@Param("communityId") Integer communityId);
    IPage<CourierPageListVO> getCourierPageList(@Param("page") IPage<CourierPageListVO> page, @Param("dto") CourierPageListDTO dto);
pt-errand/src/main/java/com/ruoyi/errand/mapper/VipOrderMapper.java
@@ -3,10 +3,13 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.errand.domain.UserCancellationLog;
import com.ruoyi.errand.domain.VipOrder;
import com.ruoyi.errand.object.vo.sys.OrderSysDetailVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface VipOrderMapper extends BaseMapper<VipOrder> {
    List<VipOrder> selectRefundVipOrder(@Param("appUserId") Integer appUserId);
    OrderSysDetailVO detail(@Param("id")Integer id);
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddAddressBookDTO.java
@@ -15,4 +15,7 @@
    private String recipientPhone;
    @ApiModelProperty("详细地址")
    private String addressDetail;
    @ApiModelProperty("地址扩展字段")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddEvaluationDTO.java
@@ -11,6 +11,9 @@
@Data
@ApiModel("评价订单")
public class AddEvaluationDTO {
    @ApiModelProperty("评价id,有就修改,没有就是新增")
    private Integer evaluationId;
    @ApiModelProperty("订单id")
    @NotNull(message = "订单id不能为空")
    private Integer orderId;
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddFeedbackDTO.java
New file
@@ -0,0 +1,12 @@
package com.ruoyi.errand.object.dto.app;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("用户意见反馈")
public class AddFeedbackDTO {
    @ApiModelProperty("反馈内容")
    private String content;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddRegisterReportDTO.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.errand.object.dto.app;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Data
@ApiModel("注册页-上报不存在小区")
public class AddRegisterReportDTO {
    @ApiModelProperty("关联省市区的区域id")
    @NotNull(message = "上报区域不能为空")
    private Integer region_id;
    @ApiModelProperty("小区名称")
    @NotEmpty(message = "小区名称不能为空")
    private String communityName;
    @ApiModelProperty("详细地址")
    @NotEmpty(message = "详细地址不能为空")
    private String addressDetail;
    @ApiModelProperty("手机号")
    @NotEmpty(message = "手机号不能为空")
    private String phone;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AddReportDTO.java
@@ -12,12 +12,17 @@
public class AddReportDTO {
    @ApiModelProperty("关联省市区的区域id")
    @NotNull(message = "上报区域不能为空")
    private Integer region_id;
    private Integer regionId;
    @ApiModelProperty("小区名称")
    @NotEmpty(message = "小区名称不能为空")
    private String communityName;
    @ApiModelProperty("详细地址")
    @NotEmpty(message = "详细地址不能为空")
    private String addressDetail;
    @ApiModelProperty("手机号")
    @NotEmpty(message = "手机号不能为空")
    private String phone;
    @ApiModelProperty("用户名")
    @NotEmpty(message = "用户名不能为空")
    private String username;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AgreementDTO.java
@@ -8,7 +8,7 @@
@Data
@ApiModel("协议DTO")
public class AgreementDTO {
    @ApiModelProperty("类型(1=用户协议,2=隐私协议,3=下单须知,4=注销协议,5=首页介绍,6=快递代拿下单说明,7=商品代买下单说明)")
    @ApiModelProperty("类型(1=用户协议,2=隐私协议,3=下单须知,4=注销协议,5=首页介绍,6=快递代拿下单说明,7=商品代买下单说明,8=会员协议)")
    private Integer type;
    @ApiModelProperty("内容")
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/AppletLogin.java
@@ -4,13 +4,18 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
@Data
@ApiModel("一键登录")
public class AppletLogin {
    @ApiModelProperty(value = "微信jscode", required = true)
    @NotEmpty(message = "微信jscode不能为空")
    private String jscode;
    @ApiModelProperty(value = "手机号加密数据", required = true)
    @NotEmpty(message = "手机号加密数据不能为空")
    private String encryptedData_phone;
    @ApiModelProperty(value = "加密算法的初始向量", required = true)
    @NotEmpty(message = "加密算法的初始向量不能为空")
    private String iv_phone;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/BirthDayDTO.java
@@ -6,11 +6,13 @@
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Data
@ApiModel("生日")
public class BirthDayDTO {
    @ApiModelProperty("生日")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate birthday;
    private Date birthday;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/ConfirmOrderDTO.java
@@ -28,7 +28,7 @@
    @NotEmpty(message = "代办事项不能为空")
    private String agencyMatters;
    @ApiModelProperty("货品件数")
    private Integer num;
    private String num;
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty("上传图片地址(多张逗号隔开,最多五张)")
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/RegisterDTO.java
@@ -10,6 +10,8 @@
@Data
@ApiModel("用户注册")
public class RegisterDTO {
    @ApiModelProperty("头像")
    private String avatar;
    @ApiModelProperty("用户名")
    @NotEmpty(message = "用户名不能为空")
    private String username;
@@ -22,4 +24,6 @@
    @ApiModelProperty("手机号")
    @NotEmpty(message = "手机号不能为空")
    private String phone;
    @ApiModelProperty("地址扩展")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/app/SetConfirmOrderDTO.java
@@ -21,7 +21,7 @@
    @ApiModelProperty("代办事项")
    private String agencyMatters;
    @ApiModelProperty("货品件数")
    private Integer num;
    private String num;
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty("上传图片地址(多张逗号隔开,最多五张)")
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/AgreementContentDTO.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.errand.object.dto.sys;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
@Data
@ApiModel("协议DTO")
public class AgreementContentDTO {
    @ApiModelProperty("代拿")
    @NotEmpty(message = "快递代拿下单说明不能为空")
    private String takeContent;
    @ApiModelProperty("代买")
    @NotEmpty(message = "商品代买下单说明不能为空")
    private String buyContent;
    @ApiModelProperty("首页介绍")
    @NotEmpty(message = "首页介绍不能为空")
    private String content;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/BannerPageDTO.java
New file
@@ -0,0 +1,13 @@
package com.ruoyi.errand.object.dto.sys;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class BannerPageDTO {
    private Integer pageNum;
    private Integer pageSize;
    @ApiModelProperty("banner名称")
    private String name;
}
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/FinanceStatisticsDTO.java
@@ -27,6 +27,9 @@
    @ApiModelProperty("类型 0-全部 1-订单 2-会员充值")
    private Integer type;
    @ApiModelProperty(" 支付方式  0-在线支付 1-会员支付")
    private Integer payMethod;
    @ApiModelProperty("0全部1待确认2进行中3已取消4已完成、已评价6已退费")
    private Integer orderStatus;
pt-errand/src/main/java/com/ruoyi/errand/object/dto/sys/SetPriceDTO.java
@@ -11,12 +11,17 @@
@Data
@ApiModel("设置会员价格")
public class SetPriceDTO {
    @ApiModelProperty("1-4对应会员 1-月卡 2-季卡 3-半年卡 4-年卡")
    @Max(value = 4,message = "id取值在1-4")
    @Min(value = 1,message = "id取值在1-4")
    private Integer id;
    @ApiModelProperty("会员价格")
    private BigDecimal vip_price;
    @ApiModelProperty("会员价格-月卡")
    private BigDecimal vipPriceOne;
    @ApiModelProperty("会员价格-季卡")
    private BigDecimal vipPriceTwo;
    @ApiModelProperty("会员价格-半年卡")
    private BigDecimal vipPriceThree;
    @ApiModelProperty("会员价格-年卡")
    private BigDecimal vipPriceFour;
    @ApiModelProperty("会员协议")
    private String content;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AddressBookByCommunityIdVO.java
@@ -24,6 +24,9 @@
    private String addressDetail;
    @ApiModelProperty("是否默认地址:0-否,1-是")
    private Integer is_default;
    private Integer isDefault;
    @ApiModelProperty("地址扩展字段")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AddressBookListVO.java
@@ -1,6 +1,7 @@
package com.ruoyi.errand.object.vo.app;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -9,14 +10,19 @@
@ApiModel("用户地址簿列表")
public class AddressBookListVO {
    @ApiModelProperty("地址ID")
    @ApiModelProperty("地址蒲ID")
    private Integer id;
    @ApiModelProperty("关联省市区的区域ID")
    private Integer regionId;
    @ApiModelProperty("关联省市区的区域名称")
    private String regionName;
    @ApiModelProperty("关联小区ID")
    private Integer communityId;
    @ApiModelProperty("小区名称")
    private Integer communityName;
    private String communityName;
    @ApiModelProperty("收件人姓名")
    private String recipientName;
@@ -28,6 +34,8 @@
    private String addressDetail;
    @ApiModelProperty("是否默认地址:0-否,1-是")
    private Integer is_default;
    private Integer isDefault;
    @ApiModelProperty("地址扩展字段")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AppUserInfoVO.java
@@ -7,6 +7,7 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ApiModel("用户个人中心信息")
@@ -27,10 +28,20 @@
    @ApiModelProperty("会员id")
    private Integer vipId;
    @ApiModelProperty("会员id")
    private Integer vipName;
    @ApiModelProperty("会员名称")
    private String vipName;
    @ApiModelProperty("会员到期时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime endTime;
    @ApiModelProperty("生日")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDateTime birthday;
    @ApiModelProperty("会员到期时间戳")
    private Long endTimeStamp;
    @ApiModelProperty("地址扩展")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/AppUserOrderListVO.java
@@ -15,45 +15,35 @@
@ApiModel("用户订单列表")
public class AppUserOrderListVO {
    @ApiModelProperty("订单id")
    @TableId(type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("详细地址")
    @TableField("address_detail")
    private String addressDetail;
    @ApiModelProperty("收件人姓名")
    @TableField("recipient_name")
    private String recipientName;
    @ApiModelProperty("收件人电话")
    @TableField("recipient_phone")
    private String recipientPhone;
    @ApiModelProperty("1待确认2进行中3已取消4已完成")
    @TableField("order_status")
    private Integer orderStatus;
    @ApiModelProperty("下单时间")
    @TableField("order_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime orderTime;
    @ApiModelProperty("评分(0.5-5.0,支持半星")
    @TableField("rating")
    private BigDecimal rating;
    @ApiModelProperty("跑腿id")
    @TableField("courier_id")
    private Integer courierId;
    @ApiModelProperty("跑腿人名称")
    @TableField("courier_name")
    private Integer courierName;
    private String courierName;
    @ApiModelProperty("跑腿人手机号")
    @TableField("courier_phone")
    private Integer courierPhone;
    private String courierPhone;
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/ConfirmOrderVO.java
@@ -29,7 +29,7 @@
    @ApiModelProperty("代办事项")
    private String agencyMatters;
    @ApiModelProperty("货品件数")
    private Integer num;
    private String num;
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty("上传图片地址(多张逗号隔开,最多五张)")
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/CourierInfoVO.java
@@ -13,5 +13,5 @@
    @ApiModelProperty("联系电话")
    private String phone;
    @ApiModelProperty("小区名称")
    private Integer communityName;
    private String communityName;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/CourierOrderListVO.java
@@ -26,6 +26,9 @@
    @ApiModelProperty("1待确认2进行中3已取消4已完成5已评价")
    private Integer orderStatus;
    /**
     * 这里实际为下单时间
     */
    @ApiModelProperty("接单时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime receivingTime;
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/OrderDetailVO.java
@@ -32,7 +32,7 @@
    private String agencyMatters;
    @ApiModelProperty("货品件数")
    private Integer num;
    private String num;
    @ApiModelProperty("备注")
    private String remark;
@@ -64,13 +64,18 @@
    @ApiModelProperty("跑腿联系电话")
    private String courierPhone;
    @ApiModelProperty("评价id")
    private Integer evaluationId;
    @ApiModelProperty("评分(0.5-5.0,支持半星")
    @TableField("rating")
    private BigDecimal rating;
    @ApiModelProperty("评价内容")
    @TableField("content")
    private String content;
    @ApiModelProperty("跑腿员-评价内容")
    private String courierRating;
    @ApiModelProperty("跑腿员-评价内容")
    private String courierContent;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/OrderPageVO.java
@@ -35,7 +35,13 @@
    private Integer isFirstOrder;
    @ApiModelProperty("会员到期时间 ")
    private LocalDateTime endTime;
    @ApiModelProperty("地址名称")
    private String regionName;
    @ApiModelProperty("地址id")
    private Integer regionId;
    @ApiModelProperty("地址扩展")
    private String regionExtend;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/app/VipInfoListVO.java
@@ -14,9 +14,9 @@
    private Integer id;
    @ApiModelProperty("会员名称")
    private String vip_name;
    private String vipName;
    @ApiModelProperty("会员价格")
    private BigDecimal vip_price;
    private BigDecimal vipPrice;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/login/LoginVO.java
@@ -13,7 +13,7 @@
    private String token;
    @ApiModelProperty("失效时间(秒)")
    private Long failureTime;
    @ApiModelProperty("跳转页面(0=首页,1=注册页)")
    @ApiModelProperty("跳转页面(1=首页,2=注册页)")
    private Integer skipPage;
    @ApiModelProperty("微信解密的手机号")
    private String phone;
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/AppUserPageListVO.java
@@ -13,7 +13,7 @@
@ApiModel("app用户管理分页(后台)")
public class AppUserPageListVO {
    @ApiModelProperty("主键")
    private Long id;
    private String id;
    @ApiModelProperty("用户")
    private String name;
    @ApiModelProperty("手机号")
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/BannerDetailVo.java
@@ -10,14 +10,13 @@
@Data
@ApiModel("banner查看详情VO")
public class BannerDetailVo {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty("主键")
    private Integer id;
    @ApiModelProperty("名称")
    @TableField("name")
    private String name;
    @ApiModelProperty("图片地址")
    @TableField("image_url")
    private String imageUrl;
    @ApiModelProperty("跳转类型(1=无跳转,2=外部链接)")
    private Integer jumpType;
}
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/CourierSysDetailVO.java
@@ -31,6 +31,13 @@
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ApiModelProperty("正面照地址")
    private String frontView;
    @ApiModelProperty("背面照地址")
    private String backView;
    @ApiModelProperty("当天接单量")
    private Integer today=0;
    @ApiModelProperty("本周接单量")
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/FeedbackPageListVO.java
@@ -23,7 +23,7 @@
    private String content;
    @ApiModelProperty("反馈时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime create_time;
    private LocalDateTime createTime;
    @ApiModelProperty("状态:0-未处理,1-已处理")
    private Integer status;
pt-errand/src/main/java/com/ruoyi/errand/object/vo/sys/FinanceStatisticsVO.java
@@ -6,6 +6,7 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@@ -13,6 +14,9 @@
public class FinanceStatisticsVO {
    @ApiModelProperty("订单id")
    private Integer id;
    @Excel(name = "金额")
    @ApiModelProperty("金额")
    private BigDecimal money;
    @Excel(name = "下单时间",width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty("下单时间")
@@ -23,6 +27,10 @@
    @ApiModelProperty("类型 1-订单 2-会员充值")
    private Integer type;
    @Excel(name = "支付方式", readConverterExp = " 0-在线支付 1-会员支付")
    @ApiModelProperty("支付方式  0-在线支付 1-会员支付")
    private Integer payMethod;
    @Excel(name = "订单编号")
    @ApiModelProperty("订单编号")
    private String orderNumber;
pt-errand/src/main/java/com/ruoyi/errand/service/AddressBookService.java
@@ -16,7 +16,7 @@
    void setDefaultAddress(Integer id);
    void add(AddAddressBookDTO addAddressBookDTO);
    Integer add(AddAddressBookDTO addAddressBookDTO);
    void set(UpdateAddressBookDTO updateAddressBookDTO);
pt-errand/src/main/java/com/ruoyi/errand/service/AppUserService.java
@@ -30,7 +30,7 @@
    R<LoginVO> appletLogin( AppletLogin appletLogin);
    void register(RegisterDTO registerDTO);
    LoginVO register(RegisterDTO registerDTO);
    OrderPageVO getOrderPage( Integer communityId);
@@ -40,7 +40,7 @@
    void setBirthDay(BirthDayDTO birth);
    void delete();
    void delete(String token);
    UserStatsVO getUserStats(LocalDateTime start, LocalDateTime end, String datePattern);
@@ -48,11 +48,15 @@
    IPage<AppUserPageListVO> getAppUserPageList( AppUserPageListDTO appUserPageListDTO);
    AppUserSysDetailVO detail(Integer id);
    AppUserSysDetailVO detail(String id);
    void froze(Integer id);
    void froze(String id);
    void refund(Integer id);
    void refund(String id);
    R refundPayMoneyCallback(RefundCallbackResult refundCallbackResult);
    R refundPayMoneyCallback(String xmlData);
    void setName(String name);
    void setAvatar(String avatar);
}
pt-errand/src/main/java/com/ruoyi/errand/service/CommunityService.java
@@ -18,7 +18,7 @@
public interface CommunityService extends IService<Community> {
    R<List<CommunityListVO>> getCommunity(Integer communityId);
    R<List<CommunityListVO>> getTotalCommunityList();
    R<List<CommunityListVO>> getTotalCommunityList(String name);
    List<AllCommunityListVO> getAllCommunityList();
pt-errand/src/main/java/com/ruoyi/errand/service/EvaluationService.java
@@ -4,6 +4,10 @@
import com.ruoyi.errand.domain.Evaluation;
import com.ruoyi.errand.object.dto.app.AddEvaluationDTO;
import javax.validation.Valid;
public interface EvaluationService extends IService<Evaluation> {
    void add( AddEvaluationDTO addEvaluationDTO);
    void edit( AddEvaluationDTO addEvaluationDTO);
}
pt-errand/src/main/java/com/ruoyi/errand/service/FeedbackService.java
@@ -3,13 +3,14 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.errand.domain.Feedback;
import com.ruoyi.errand.object.dto.app.AddFeedbackDTO;
import com.ruoyi.errand.object.dto.sys.FeedbackPageListDTO;
import com.ruoyi.errand.object.vo.sys.FeedbackPageListVO;
import javax.validation.Valid;
public interface FeedbackService extends IService<Feedback> {
    void add(String content);
    void add(AddFeedbackDTO dto);
    IPage<FeedbackPageListVO> getFeedbackPageList(FeedbackPageListDTO feedbackPageListDTO);
pt-errand/src/main/java/com/ruoyi/errand/service/OrderService.java
@@ -18,6 +18,7 @@
import com.ruoyi.errand.object.vo.sys.OrderSysDetailVO;
import com.ruoyi.errand.utils.RefundCallbackResult;
import com.ruoyi.errand.utils.UniPayCallbackResult;
import com.ruoyi.errand.utils.wx.PayResult;
import javax.validation.Valid;
import java.time.LocalDateTime;
@@ -29,7 +30,7 @@
    R orderPayment(ConfirmOrderDTO confirmOrderDTO);
    R orderPaymentCallback(UniPayCallbackResult uniPayCallbackResult);
    R orderPaymentCallback(PayResult payResult);
    void closeOrder();
@@ -41,7 +42,7 @@
    void cancelOrder(Integer id);
    R refundPayMoneyCallback(RefundCallbackResult refundCallbackResult);
    R refundPayMoneyCallback(String xmlData);
    OrderTopInfoVO orderTopInfo(Integer communityId);
pt-errand/src/main/java/com/ruoyi/errand/service/ReportService.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.errand.domain.Report;
import com.ruoyi.errand.object.dto.app.AddRegisterReportDTO;
import com.ruoyi.errand.object.dto.app.AddReportDTO;
import com.ruoyi.errand.object.dto.sys.ReportPageListDTO;
import com.ruoyi.errand.object.vo.sys.ReportPageListVO;
pt-errand/src/main/java/com/ruoyi/errand/service/VipOrderService.java
@@ -4,13 +4,17 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.domain.VipOrder;
import com.ruoyi.errand.object.dto.app.VipPaymentDTO;
import com.ruoyi.errand.object.vo.sys.OrderSysDetailVO;
import com.ruoyi.errand.utils.UniPayCallbackResult;
import com.ruoyi.errand.utils.wx.PayResult;
public interface VipOrderService extends IService<VipOrder> {
    R vipPayment(VipPaymentDTO vipPaymentDTO);
    R orderPaymentCallback(UniPayCallbackResult uniPayCallbackResult);
    R orderPaymentCallback(PayResult payResult);
    void closeOrder();
    OrderSysDetailVO detail(Integer id);
}
pt-errand/src/main/java/com/ruoyi/errand/service/VipSettingService.java
@@ -12,4 +12,6 @@
    List<VipInfoListVO> getVipInfoList();
    void setPrice( SetPriceDTO setPriceDTO);
    SetPriceDTO getPrice();
}
pt-errand/src/main/java/com/ruoyi/errand/service/impl/AddressBookServiceImpl.java
@@ -9,8 +9,10 @@
import com.ruoyi.errand.domain.AddressBook;
import com.ruoyi.errand.domain.AppUser;
import com.ruoyi.errand.domain.Community;
import com.ruoyi.errand.domain.Region;
import com.ruoyi.errand.mapper.AddressBookMapper;
import com.ruoyi.errand.mapper.CommunityMapper;
import com.ruoyi.errand.mapper.RegionMapper;
import com.ruoyi.errand.object.dto.app.AddAddressBookDTO;
import com.ruoyi.errand.object.dto.app.UpdateAddressBookDTO;
import com.ruoyi.errand.object.vo.app.AddressBookByCommunityIdVO;
@@ -27,6 +29,8 @@
public class AddressBookServiceImpl extends ServiceImpl<AddressBookMapper, AddressBook> implements AddressBookService {
    @Resource
    private CommunityMapper communityMapper;
    @Resource
    private RegionMapper regionMapper;
    @Override
    public List<AddressBookByCommunityIdVO> addressBookByCommunityId(Integer communityId) {
@@ -42,38 +46,64 @@
    @Override
    public List<AddressBookListVO> addressBookList() {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return this.getBaseMapper().addressBookList(appuser.getId());
        List<AddressBookListVO> voList = this.getBaseMapper().addressBookList(appuser.getId());
        voList.forEach(vo->{
            String regionFullName = getRegionFullName(vo.getRegionId());
            vo.setRegionName(regionFullName);
        });
        return voList;
    }
    /**
     * 根据区ID查询完整的省市区名称
     */
    public String getRegionFullName(Integer districtId) {
        Region district = regionMapper.selectById(districtId);
        if (district == null) {
            return "";
        }
        Region city = regionMapper.selectById(district.getParentId());
        if (city == null) {
            return district.getName();
        }
        Region province = regionMapper.selectById(city.getParentId());
        if (province == null) {
            return city.getName()  + district.getName();
        }
        return province.getName()  + city.getName()  + district.getName();
    }
    @Override
    public void setDefaultAddress(Integer id) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //查询这个默认地址
        AddressBook addressBook = this.getById(id);
        if (null==addressBook||addressBook.getDel_flag().equals(DelFlagConstant.DELETE)) {
        if (null==addressBook||addressBook.getDelFlag().equals(DelFlagConstant.DELETE)) {
            throw new ServiceException("该地址不存在");
        }
        //查看原本小区内是否有默认地址
        List<AddressBook> addressBooks = this.getBaseMapper().selectList(new LambdaUpdateWrapper<AddressBook>()
                .eq(AddressBook::getCommunityId, addressBook.getCommunityId())
                .eq(AddressBook::getApp_user_id, appuser.getId())
                .eq(AddressBook::getDel_flag, DelFlagConstant.UNDELETE)
                .eq(AddressBook::getIs_default, IsDefaultConstant.TRUE)
                .eq(AddressBook::getAppUserId, appuser.getId())
                .eq(AddressBook::getDelFlag, DelFlagConstant.UNDELETE)
                .eq(AddressBook::getIsDefault, IsDefaultConstant.TRUE)
        );
        //将原本地址修改掉
        addressBooks.forEach(x->{
            x.setIs_default(IsDefaultConstant.FALSE);
            x.setUpdate_time(LocalDateTime.now());
            x.setIsDefault(IsDefaultConstant.FALSE);
            x.setUpdateTime(LocalDateTime.now());
            this.getBaseMapper().updateById(x);}
        );
        //将新地址设置为默认地址
        addressBook.setIs_default(IsDefaultConstant.TRUE);
        addressBook.setUpdate_time(LocalDateTime.now());
        addressBook.setIsDefault(IsDefaultConstant.TRUE);
        addressBook.setUpdateTime(LocalDateTime.now());
        this.getBaseMapper().updateById(addressBook);
    }
    @Override
    public void add(AddAddressBookDTO addAddressBookDTO) {
    public Integer add(AddAddressBookDTO addAddressBookDTO) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //判断小区是否存在
        Community community = communityMapper.selectById(addAddressBookDTO.getCommunityId());
@@ -82,10 +112,11 @@
        }
        AddressBook addressBook = new AddressBook();
        BeanUtils.copyProperties(addAddressBookDTO,addressBook);
        addressBook.setIs_default(IsDefaultConstant.FALSE);
        addressBook.setCreate_time(LocalDateTime.now());
        addressBook.setApp_user_id(appuser.getId());
        addressBook.setIsDefault(IsDefaultConstant.FALSE);
        addressBook.setCreateTime(LocalDateTime.now());
        addressBook.setAppUserId(appuser.getId());
        this.save(addressBook);
        return addressBook.getId();
    }
    @Override
@@ -98,15 +129,15 @@
        }
        //判断地址是否存在
        AddressBook addressBook = this.getById(updateAddressBookDTO.getId());
        if (null==addressBook||addressBook.getDel_flag().equals(DelFlagConstant.DELETE)) {
        if (null==addressBook||addressBook.getDelFlag().equals(DelFlagConstant.DELETE)) {
            throw new ServiceException("地址不存在");
        }
        //判断用户是否同一个
        if (!appuser.getId().equals(addressBook.getApp_user_id())) {
        if (!appuser.getId().equals(addressBook.getAppUserId())) {
            throw new ServiceException("该地址不属于您");
        }
        BeanUtils.copyProperties(updateAddressBookDTO,addressBook);
        addressBook.setUpdate_time(LocalDateTime.now());
        addressBook.setUpdateTime(LocalDateTime.now());
        this.updateById(addressBook);
    }
@@ -116,15 +147,15 @@
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //查看该地址是否存在
        AddressBook addressBook = this.getById(id);
        if (null==addressBook||addressBook.getDel_flag().equals(DelFlagConstant.DELETE)) {
        if (null==addressBook||addressBook.getDelFlag().equals(DelFlagConstant.DELETE)) {
            throw new ServiceException("该地址不存在");
        }
        //判断用户是否同一个
        if (!appuser.getId().equals(addressBook.getApp_user_id())) {
        if (!appuser.getId().equals(addressBook.getAppUserId())) {
            throw new ServiceException("该地址不属于您");
        }
        addressBook.setDel_flag(DelFlagConstant.DELETE);
        addressBook.setDelFlag(DelFlagConstant.DELETE);
        this.updateById(addressBook);
    }
}
pt-errand/src/main/java/com/ruoyi/errand/service/impl/AppUserServiceImpl.java
@@ -4,6 +4,7 @@
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -11,16 +12,10 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.errand.constant.*;
import com.ruoyi.errand.domain.AppUser;
import com.ruoyi.errand.domain.*;
import com.ruoyi.errand.domain.Order;
import com.ruoyi.errand.domain.UserCancellationLog;
import com.ruoyi.errand.domain.VipOrder;
import com.ruoyi.errand.mapper.AppUserMapper;
import com.ruoyi.errand.mapper.*;
import com.ruoyi.errand.mapper.OrderMapper;
import com.ruoyi.errand.mapper.UserCancellationLogMapper;
import com.ruoyi.errand.mapper.VipOrderMapper;
import com.ruoyi.errand.object.dto.app.AppletLogin;
import com.ruoyi.errand.object.dto.app.BirthDayDTO;
import com.ruoyi.errand.object.dto.app.MobileLoginDTO;
@@ -35,7 +30,11 @@
import com.ruoyi.errand.object.vo.sys.OrderPageListVO;
import com.ruoyi.errand.object.vo.sys.UserStatsVO;
import com.ruoyi.errand.service.AppUserService;
import com.ruoyi.errand.service.CommunityCourierService;
import com.ruoyi.errand.utils.*;
import com.ruoyi.errand.utils.sms.AliyunSmsService;
import com.ruoyi.errand.utils.wx.RefundCallbackResult;
import com.ruoyi.errand.utils.wx.WechatPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,9 +42,11 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
@@ -68,6 +69,21 @@
    private OrderMapper orderMapper;
    @Autowired
    private VipOrderMapper vipOrderMapper;
    @Autowired
    private WechatPayService wechatPayService;
    @Autowired
    private AppUserService appUserService;
    @Autowired
    private CommunityCourierMapper communityCourierMapper;
    @Autowired
    private CommunityCourierService communityCourierService;
    @Autowired
    private CourierMapper courierMapper;
    @Autowired
    private CommunityMapper communityMapper;
    @Autowired
    private TokenBlacklistService blacklistService;
    @Override
@@ -100,7 +116,7 @@
        for (int i = 0; i < 6; i++) {
            code += Double.valueOf(Math.random() * 10).intValue();
        }
        SMSUtil.sendSms("[\"" + code + "\"]", phone, "8824121211029", "39533d100b2b4aee8ed198aa49fe99dd");
        AliyunSmsService.sendVerificationCode(phone,code);
        redisService.setCacheObject(phone, code, 300L, TimeUnit.SECONDS);
    }
@@ -116,7 +132,7 @@
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, mobileLogin.getPhone())
                .ne(AppUser::getStatus,AppUserStatusConstant.LOGOUT)
                .eq(AppUser::getDelFlag,DelFlagConstant.UNDELETE));
        if (null == appUser) {
        if (null == appUser || null == appUser.getWxOpenid()) {
            //用户不存在
            //跳转注册页面
            LoginVO loginVo = new LoginVO();
@@ -142,7 +158,7 @@
        loginVO.setToken("app:" + jwt.get("token").toString());
        loginVO.setFailureTime(TimeUnit.MILLISECONDS.toSeconds((long)jwt.get("exp")));
        loginVO.setPhone(appUser.getPhone());
        loginVO.setSkipPage(appUser.getFirstLogin());
        loginVO.setSkipPage(1);
        loginVO.setIsCourier(appUser.getCourierId()!=null);
        return R.ok(loginVO);
    }
@@ -166,7 +182,7 @@
        String phone = phoneJson.getString("phoneNumber");
        //查询用户是否存在
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, phone).ne(AppUser::getStatus, AppUserStatusConstant.LOGOUT).eq(AppUser::getDelFlag,DelFlagConstant.UNDELETE));
        if(null == appUser){
        if(null == appUser || null == appUser.getWxOpenid()){
            //跳转到注册界面
            LoginVO loginVo = new LoginVO();
            loginVo.setSkipPage(2);
@@ -182,7 +198,7 @@
        }
        //构建token
        Map<String,Object> tokenMap = new HashMap<>();
        map.put("userId",appUser.getId());
        tokenMap.put("userId",appUser.getId());
        Map<String, Object> jwt = JwtUtil.createJWT(tokenMap);
@@ -190,12 +206,13 @@
        loginVO.setToken("app:" + jwt.get("token").toString());
        loginVO.setFailureTime(TimeUnit.MILLISECONDS.toSeconds((long)jwt.get("exp")));
        loginVO.setPhone(appUser.getPhone());
        loginVO.setSkipPage(appUser.getFirstLogin());
        loginVO.setSkipPage(1);
        loginVO.setIsCourier(appUser.getCourierId()!=null);
        return R.ok(loginVO);
    }
    @Override
    public void register(RegisterDTO registerDTO) {
    public LoginVO register(RegisterDTO registerDTO) {
        //使用jscode获取微信openid
        Map<String, Object> map = weChatUtil.code2Session(registerDTO.getJscode());
        Integer errcode = Integer.valueOf(map.get("errcode").toString());
@@ -203,28 +220,45 @@
            throw new ServiceException(map.get("msg").toString());
        }
        String openid = map.get("openid").toString();
        AppUser appUser1 = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getWxOpenid, openid).ne(AppUser::getStatus, AppUserStatusConstant.LOGOUT).eq(AppUser::getDelFlag,DelFlagConstant.UNDELETE));
        if (null != appUser1) {
            throw new ServiceException("此微信号已注册,请直接登录!");
        }
        AppUser appUser2 = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, registerDTO.getPhone()).ne(AppUser::getStatus, AppUserStatusConstant.LOGOUT).eq(AppUser::getDelFlag,DelFlagConstant.UNDELETE));
        if (null != appUser2) {
        if (null != appUser2 && appUser2.getWxOpenid() !=null) {
            throw new ServiceException("手机号已注册,请直接登录!");
        }
        //注册一个
        AppUser appUser = new AppUser();
        appUser.setPhone(registerDTO.getPhone());
        appUser.setDelFlag(DelFlagConstant.UNDELETE);
        appUser.setStatus(AppUserStatusConstant.NORMAL);
        appUser.setWxOpenid(openid);
        appUser.setAvatar(DEFAULT_AVATAR_URL);
        appUser.setFirstLogin(IsFirstLoginConstant.YES);
        appUser.setFirstOrder(IsFirstOrder.YES);
        //注册 修改用户信息
        appUser.setName(registerDTO.getUsername());
        appUser.setFirstLogin(IsFirstLoginConstant.NO);
        appUser.setCommunityId(registerDTO.getCommunityId());
        this.updateById(appUser);
        if (appUser2 ==null) {
            appUser2 = new AppUser();
            //注册一个
            appUser2.setPhone(registerDTO.getPhone());
            appUser2.setDelFlag(DelFlagConstant.UNDELETE);
            appUser2.setStatus(AppUserStatusConstant.NORMAL);
            appUser2.setWxOpenid(openid);
            appUser2.setFirstLogin(IsFirstLoginConstant.YES);
            appUser2.setFirstOrder(IsFirstOrder.YES);
        }
        //修改
        appUser2.setName(registerDTO.getUsername());
        appUser2.setAvatar(registerDTO.getAvatar()==null?DEFAULT_AVATAR_URL:registerDTO.getAvatar());
        appUser2.setCommunityId(registerDTO.getCommunityId());
        appUser2.setWxOpenid(openid);
        appUser2.setPhone(registerDTO.getPhone());
        appUser2.setCreateTime(LocalDateTime.now());
        appUser2.setRegionExtend(registerDTO.getRegionExtend());
        this.saveOrUpdate(appUser2);
        //构建token
        Map<String,Object> tokenMap = new HashMap<>();
        tokenMap.put("userId",appUser2.getId());
        Map<String, Object> jwt = JwtUtil.createJWT(tokenMap);
        LoginVO loginVO=new LoginVO();
        loginVO.setToken("app:" + jwt.get("token").toString());
        loginVO.setFailureTime(TimeUnit.MILLISECONDS.toSeconds((long)jwt.get("exp")));
        loginVO.setPhone(appUser2.getPhone());
        loginVO.setSkipPage(1);
        loginVO.setIsCourier(appUser2.getCourierId()!=null);
        return loginVO;
    }
@@ -232,19 +266,55 @@
    public OrderPageVO getOrderPage(Integer communityId) {
        AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //更换绑定的小区
        if (communityId!=null){
        if (communityId!=null&& !Objects.equals(appUser.getCommunityId(), communityId)){
            appUser.setCommunityId(communityId);
            this.updateById(appUser);
        }
        List<OrderPageVO> orderPage = this.getBaseMapper().getOrderPage(appUser.getId());
        Community community = communityMapper.selectById(appUser.getCommunityId());
        String regionFullName = getRegionFullName(community.getRegionId());
        orderPage.get(0).setRegionName(regionFullName);
        orderPage.get(0).setRegionId(community.getRegionId());
        return orderPage.get(0);
    }
    @Autowired
    private RegionMapper regionMapper;
    /**
     * 根据区ID查询完整的省市区名称
     */
    public String getRegionFullName(Integer districtId) {
        Region district = regionMapper.selectById(districtId);
        if (district == null) {
            return "";
        }
        Region city = regionMapper.selectById(district.getParentId());
        if (city == null) {
            return district.getName();
        }
        Region province = regionMapper.selectById(city.getParentId());
        if (province == null) {
            return city.getName()  + district.getName();
        }
        return province.getName()  + city.getName()  + district.getName();
    }
    @Override
    public AppUserInfoVO getMyInfo() {
        AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return this.getBaseMapper().getMyInfo(appUser.getId());
        AppUserInfoVO myInfo = this.getBaseMapper().getMyInfo(appUser.getId());
        myInfo.setEndTimeStamp(myInfo.getEndTime() != null ?
                myInfo.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() :
                null);
        if (myInfo.getEndTime() != null) {
            if(myInfo.getEndTime().isBefore(LocalDateTime.now())){
                myInfo.setVipId(null);
            }
        }
        return myInfo;
    }
    @Override
@@ -270,16 +340,44 @@
     * 注销账号
     */
    @Override
    public void delete() {
    public void delete(String token) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        appuser.setDelFlag(DelFlagConstant.DELETE);
        appuser.setStatus(AppUserStatusConstant.LOGOUT);
        this.updateById(appuser);
        //跑腿员 订单是否完成
        if (appuser.getCourierId()!=null){
            //跑腿员
            Courier courier = courierMapper.selectById(appuser.getCourierId());
            if (null != courier && courier.getDelFlag().equals(DelFlagConstant.UNDELETE)) {
                //查订单是否完成
                Long count = orderMapper.selectCount(new LambdaUpdateWrapper<Order>().eq(Order::getCourierId, appuser.getCourierId())
                        .eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
                        .eq(Order::getOrderStatus, 2));
                if (count > 0) {
                    throw new ServiceException("您还有订单未完成,无法注销");
                }
            }
            //与小区关系删除
            CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>().eq(CommunityCourier::getCourierId, appuser.getCourierId()));
            if (null != communityCourier) {
                communityCourierMapper.deleteById(communityCourier.getId());
            }
            //跑腿员删除
            courier.setDelFlag(DelFlagConstant.DELETE);
            courierMapper.updateById(courier);
        }
        UpdateWrapper<AppUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", appuser.getId())
                .set("courier_id", null)
                .set("del_flag", DelFlagConstant.DELETE)
                        .set("status",AppUserStatusConstant.LOGOUT);
        this.getBaseMapper().update(null, updateWrapper);
        UserCancellationLog userCancellationLog=new UserCancellationLog();
        userCancellationLog.setApp_user_id(appuser.getId());
        userCancellationLog.setDel_flag(DelFlagConstant.DELETE);
        userCancellationLog.setCreate_time(LocalDateTime.now());
        userCancellationLogMapper.insert(userCancellationLog);
        blacklistService.addToBlacklist(token);
    }
    @Override
@@ -334,12 +432,15 @@
    }
    @Override
    public AppUserSysDetailVO detail(Integer id) {
    public AppUserSysDetailVO detail(String id) {
        // 获取本月的开始时间和结束时间
        LocalDate now = LocalDate.now();
        LocalDateTime startOfMonth = now.withDayOfMonth(1).atStartOfDay();
        LocalDateTime endOfMonth = now.withDayOfMonth(now.lengthOfMonth()).atTime(23, 59, 59);
        AppUser appUser = this.getBaseMapper().selectById(id);
        if (null == appUser || appUser.getDelFlag() == DelFlagConstant.DELETE) {
            throw new ServiceException("用户不存在");
        }
        AppUserSysDetailVO vo = new AppUserSysDetailVO();
        BeanUtils.copyProperties(appUser, vo);
        int isVip =0;
@@ -365,7 +466,7 @@
    }
    @Override
    public void froze(Integer id) {
    public void froze(String id) {
        AppUser appUser = this.getBaseMapper().selectById(id);
        if (appUser==null|| Objects.equals(appUser.getDelFlag(), DelFlagConstant.DELETE)) {
            throw new ServiceException("用户不存在");
@@ -382,13 +483,14 @@
    }
    @Override
    public void refund(Integer id) {
    public void refund(String id) {
        // 1. 查询用户所有未退费的VIP订单(状态为4-已完成且未删除)
        List<VipOrder> orders = vipOrderMapper.selectList(new LambdaQueryWrapper<VipOrder>()
                .eq(VipOrder::getAppUserId, id)
                .eq(VipOrder::getOrderStatus, 4) // 4-已完成
                .eq(VipOrder::getDelFlag, DelFlagConstant.UNDELETE)     // 0-未删除
                .isNull(VipOrder::getRefundTime) // 未退款的
                        .eq(VipOrder::getPayStatus,2)
                .orderByDesc(VipOrder::getOrderTime));
        // 2. 计算每个订单的有效期结束时间
@@ -410,29 +512,55 @@
            //退款
            log.info("开始会员退费,被退款人员id:{},退款订单:{}",vipOrder.getAppUserId(),vipOrder.getId());
            R r = refundPayMoney(vipOrder);//退款
            if (200 == r.getCode()) {
                //退款成功取消用户的会员,将用户状态改变
                AppUser appUser = this.getById(id);
                appUser.setStartTime(LocalDateTime.now());
                appUser.setEndTime(LocalDateTime.now());
                appUser.setVipId(null);
            if (200 != r.getCode()) {
                throw new ServiceException("退款失败,msg:"+ r.getMsg()+" 订单id:"+vipOrder.getId());
            }
        });
        UpdateWrapper<AppUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id)
                .set("vip_id", null)        // 显式设置vip_id为null
                .set("end_time", LocalDateTime.now());  // 设置结束时间
        appUserService.update(null, updateWrapper);
    }
    @Override
    public R refundPayMoneyCallback(RefundCallbackResult refundCallbackResult) {
        String code = refundCallbackResult.getR3_RefundOrderNo().substring(1);
        VipOrder vipOrder = vipOrderMapper.selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber, code));
    public R refundPayMoneyCallback(String xmlData) {
        RefundCallbackResult result = wechatPayService.processRefundCallback(xmlData);
        if (!result.isSuccess()) {
            System.out.println("会员退费错误:"+result.getMsg());
            return R.fail(result.getMsg());
        }
        VipOrder vipOrder = vipOrderMapper.selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber,  result.getOrderNo()));
        if (null == vipOrder || vipOrder.getPayStatus() == 1 || vipOrder.getOrderStatus() == 6) {
            return R.ok();
        }
        vipOrder.setRefundCode(refundCallbackResult.getR5_RefundTrxNo());
        vipOrder.setRefundCode(result.getRefundNo());
        vipOrder.setRefundStatus(2);
        vipOrder.setRefundTime(LocalDateTime.now());
        vipOrder.setOrderStatus(6);//已退费
        vipOrderMapper.updateById(vipOrder);
        //退款成功取消用户的会员,将用户状态改变
        UpdateWrapper<AppUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", vipOrder.getAppUserId())
                .set("vip_id", null)        // 显式设置vip_id为null
                .set("end_time", LocalDateTime.now());  // 设置结束时间
        appUserService.update(null, updateWrapper);
        return R.ok();
    }
    @Override
    public void setName(String name) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        appuser.setName(name);
        this.updateById(appuser);
    }
    @Override
    public void setAvatar(String avatar) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        appuser.setAvatar(avatar);
        this.updateById(appuser);
    }
    private Map<Long, LocalDateTime> calculateOrderEndTimes(List<VipOrder> orders) {
@@ -484,11 +612,14 @@
        BigDecimal paymentAmount = order.getPaymentAmount();
        if (BigDecimal.ZERO.compareTo(order.getPaymentAmount()) < 0) {//支付的金额是否大于0
            //微信退款
            RefundResult refund = PaymentUtil.refund(order.getOrderNumber(), "R" + order.getOrderNumber(), paymentAmount.doubleValue(),
                    "/app/user/refundPayMoneyCallback");
            if (!"100".equals(refund.getRa_Status())) {
                return R.fail(refund.getRc_CodeMsg());//退款失败
            Map<String,String> map = wechatPayService.refund(order.getOrderNumber(), order.getOrderNumber(), order.getPaymentAmount().toString(), order.getPaymentAmount().toString(), "会员退款", "/app/user/refundPayMoneyCallback");
            if (!"SUCCESS".equals(map.get("return_code"))) {
                return R.fail(map.get("return_msg"));//退款失败
            }
            //这里申请成功后先返回,等待微信退款成功再取消用户会员
            order.setRefundStatus(1);
            vipOrderMapper.updateById(order);
            return R.ok();
        }
        return R.ok();
    }
pt-errand/src/main/java/com/ruoyi/errand/service/impl/CommunityServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.errand.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -25,6 +26,7 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -55,15 +57,18 @@
    }
    @Override
    public R<List<CommunityListVO>> getTotalCommunityList() {
        List<CommunityListVO> communityListVOS = this.getBaseMapper().getTotalCommunityList();
    public R<List<CommunityListVO>> getTotalCommunityList(String name) {
        List<CommunityListVO> communityListVOS = this.getBaseMapper().getTotalCommunityList(name);
        return R.ok(communityListVOS);
    }
    @Override
    public List<AllCommunityListVO> getAllCommunityList() {
        List<Integer> list=communityCourierMapper.getAllCommunityList();
        return this.baseMapper.getAllCommunityList(list);
            return this.baseMapper.getAllCommunityList(list);
    }
    @Override
@@ -73,6 +78,7 @@
        iPage.getRecords().forEach(x->{
            List<Order> orderList = orderMapper.selectList(new LambdaQueryWrapper<Order>()
                    .eq(Order::getCommunityId, x.getId())
                            .ne(Order::getOrderStatus,3)
                    .eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
                    .eq(Order::getPayStatus,2));
            if (orderList!=null&& !orderList.isEmpty()){
@@ -111,12 +117,15 @@
        //添加小区
        Community community = new Community();
        BeanUtils.copyProperties(addCommunityDTO,community);
        community.setDelFlag(0);
        community.setStatus(0);
        community.setCreateTime(LocalDateTime.now());
        this.save(community);
        if (addCommunityDTO.getServicePhone()!=null){
            //保存客服电话
            Phone phone = new Phone();
            phone.setType(2);
            phone.setCommunity_id(community.getId());
            phone.setCommunityId(community.getId());
            phone.setPhone(addCommunityDTO.getServicePhone());
            phoneMapper.insert(phone);
        }
@@ -148,14 +157,14 @@
        //检查客服电话是否更改
        if (editCommunityDTO.getServicePhone()!=null){
            Phone phone = phoneMapper.selectOne(new LambdaQueryWrapper<Phone>()
                    .eq(Phone::getCommunity_id, editCommunityDTO.getId())
                    .eq(Phone::getCommunityId, editCommunityDTO.getId())
                    .eq(Phone::getType, 2));
            if (phone==null){
                //添加
                //保存客服电话
                phone = new Phone();
                phone.setType(2);
                phone.setCommunity_id(community.getId());
                phone.setCommunityId(community.getId());
                phone.setPhone(editCommunityDTO.getServicePhone());
                phoneMapper.insert(phone);
            }else {
@@ -171,10 +180,10 @@
            throw new ServiceException("跑腿人员不存在");
        }
        //检查跑腿员是否绑定
        Long count = communityCourierMapper.selectCount(new LambdaQueryWrapper<CommunityCourier>()
        CommunityCourier one = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>()
                .eq(CommunityCourier::getCourierId, editCommunityDTO.getCourierId()));
        if (count>0){
            throw new ServiceException("跑腿人员已绑定");
        if (one != null && !Objects.equals(one.getCommunityId(), editCommunityDTO.getId())){
            throw new ServiceException("跑腿人员已绑定其他小区");
        }
        //检查跑腿员是否更改
        CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>()
@@ -184,12 +193,16 @@
            communityCourier = new CommunityCourier();
            communityCourier.setCommunityId(editCommunityDTO.getId());
            communityCourier.setCourierId(editCommunityDTO.getCourierId());
            communityCourierMapper.insert(communityCourier);
        }else {
            //修改
            communityCourier.setCourierId(editCommunityDTO.getCourierId());
            communityCourierMapper.updateById(communityCourier);
        }
        //修改小区
        BeanUtils.copyProperties(editCommunityDTO,community);
        this.updateById(community);
    }
    @Override
@@ -197,6 +210,14 @@
        Community community = this.baseMapper.selectById(id);
        if (community==null|| Objects.equals(community.getDelFlag(), DelFlagConstant.DELETE)){
            throw new ServiceException("未找到该小区");
        }
        //查找小区是否有订单未完成
        //查找小区是否有订单未完成
        Long count = orderMapper.selectCount(new LambdaUpdateWrapper<Order>().eq(Order::getCommunityId, id)
                .eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
                .in(Order::getOrderStatus, Arrays.asList(1,2)));
        if (count > 0) {
            throw new ServiceException("该小区还有订单未完成,无法冻结");
        }
        //删除关系
        CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>()
@@ -217,6 +238,16 @@
        if (community==null|| Objects.equals(community.getDelFlag(), DelFlagConstant.DELETE)){
            throw new ServiceException("未找到该小区");
        }
        if (community.getStatus()==1){
            //查找小区是否有订单未完成
            Long count = orderMapper.selectCount(new LambdaUpdateWrapper<Order>().eq(Order::getCommunityId, id)
                    .eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
                    .in(Order::getOrderStatus, Arrays.asList(1,2)));
            if (count > 0) {
                throw new ServiceException("该小区还有订单未完成,无法冻结");
            }
        }
        community.setStatus(community.getStatus()==0?1:0);
        community.setUpdateTime(LocalDateTime.now());
        this.baseMapper.updateById(community);
@@ -244,10 +275,24 @@
            }
        }
        //客服电话
        Phone phone = phoneMapper.selectOne(new LambdaQueryWrapper<Phone>().eq(Phone::getCommunity_id, community.getId()));
        Phone phone = phoneMapper.selectOne(new LambdaQueryWrapper<Phone>().eq(Phone::getCommunityId, community.getId()));
        if (phone!=null){
            vo.setServicePhone(phone.getPhone());
        }
        //订单统计
        List<Order> orderList = orderMapper.selectList(new LambdaQueryWrapper<Order>()
                .eq(Order::getCommunityId,id)
                .ne(Order::getOrderStatus,3)
                .eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
                .eq(Order::getPayStatus,2));
        if (orderList!=null&& !orderList.isEmpty()){
            vo.setTotal(orderList.size());//总订单数
            LocalDateTime start = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
            LocalDateTime end = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
            long today = orderList.stream().filter(order -> order.getOrderTime().isAfter(start.minusNanos(1)))
                    .filter(order -> order.getOrderTime().isBefore(end.plusNanos(1))).count();
            vo.setToday((int) today);//今日订单数
        }
        return vo;
    }
pt-errand/src/main/java/com/ruoyi/errand/service/impl/CourierServiceImpl.java
@@ -2,12 +2,16 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.errand.constant.AppUserStatusConstant;
import com.ruoyi.errand.constant.DelFlagConstant;
import com.ruoyi.errand.constant.IsFirstLoginConstant;
import com.ruoyi.errand.constant.IsFirstOrder;
import com.ruoyi.errand.domain.*;
import com.ruoyi.errand.mapper.*;
import com.ruoyi.errand.object.dto.sys.AddCourierDTO;
@@ -36,6 +40,7 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -56,6 +61,10 @@
    private AppUserMapper appUserMapper;
    @Autowired
    private CommunityMapper communityMapper;
    @Autowired
    private AppUserService appUserService;
    @Autowired
    private CourierMapper courierMapper;
    @Override
@@ -79,8 +88,15 @@
    @Override
    public IPage<CourierOrderListVO> getCourierOrderList(Integer pageNum, Integer pageSize, Integer orderStatus) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(appuser.getCourierId()==null){
            throw new ServiceException("您已不是跑腿员");
        }
        IPage<CourierOrderListVO> page=new Page<>(pageNum, pageSize);
        return this.baseMapper.getCourierOrderList(page,orderStatus,appuser.getCourierId());
        CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>().eq(CommunityCourier::getCourierId, appuser.getCourierId()));
        if (communityCourier==null){
            throw new ServiceException("您还未绑定需代办的小区");
        }
        return this.baseMapper.getCourierOrderList(page,appuser.getCourierId(),orderStatus,communityCourier.getCommunityId());
    }
    @Override
@@ -88,6 +104,13 @@
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (appuser.getCourierId()==null){
            throw new ServiceException("您还不是跑腿员");
        }
        Courier courier = courierMapper.selectById(appuser.getCourierId());
        if (courier==null || courier.getDelFlag().equals(DelFlagConstant.DELETE)){
            throw new ServiceException("绑定的跑腿账号已失效");
        }
        if (courier.getStatus().equals(0)){
            throw new ServiceException("跑腿账号已在离职中,不能接单");
        }
        CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>().eq(CommunityCourier::getCourierId, appuser.getCourierId()));
        if(communityCourier==null){
@@ -107,6 +130,7 @@
        //修改订单状态
        order.setOrderStatus(2);
        order.setCourierId(appuser.getCourierId());
        order.setReceivingTime(LocalDateTime.now());
        orderMapper.updateById(order);
@@ -161,7 +185,8 @@
            List<Order> orderList = orderMapper.selectList(new LambdaUpdateWrapper<Order>()
                    .eq(Order::getCourierId, x.getId())
                    .eq(Order::getDelFlag,DelFlagConstant.UNDELETE)
                    .eq(Order::getPayMethod,2));
                    .notIn(Order::getOrderStatus,Arrays.asList(1,3))
                    .eq(Order::getPayStatus,2));
            if (orderList!=null&& !orderList.isEmpty()){
                //当天接单量
                LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
@@ -202,7 +227,8 @@
        List<Order> orderList = orderMapper.selectList(new LambdaUpdateWrapper<Order>()
                .eq(Order::getCourierId, id)
                .eq(Order::getDelFlag,DelFlagConstant.UNDELETE)
                .eq(Order::getPayMethod,2));
                .notIn(Order::getOrderStatus,Arrays.asList(1,3)) //未接单 取消掉的不要
                .eq(Order::getPayStatus,2));
        if (orderList!=null&& !orderList.isEmpty()){
            //当天接单量
            LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
@@ -238,13 +264,20 @@
        return vo;
    }
    private static final String DEFAULT_AVATAR_URL = "http://qijishenghuiyuan.obs.cn-southwest-2.myhuaweicloud.com/admin/aedfbbb41280471f8d9fa7905298b65f.png";
    @Override
    public void add(AddCourierDTO addCourierDTO) {
        AppUser appUser = appUserMapper.selectOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, addCourierDTO.getPhone()).
                eq(AppUser::getDelFlag, DelFlagConstant.UNDELETE));
        if (appUser == null) {
            throw new ServiceException("请先注册小程序");
            appUser=new AppUser();
            appUser.setPhone(addCourierDTO.getPhone());
            appUser.setDelFlag(DelFlagConstant.UNDELETE);
            appUser.setStatus(AppUserStatusConstant.NORMAL);
            appUser.setAvatar(DEFAULT_AVATAR_URL);
            appUser.setFirstLogin(IsFirstLoginConstant.YES);
            appUser.setFirstOrder(IsFirstOrder.YES);
            appUser.setName(addCourierDTO.getPhone());
        }
        //手机号是否存在
        Courier courier = this.getBaseMapper().selectOne(new LambdaQueryWrapper<Courier>().eq(Courier::getPhone, addCourierDTO.getPhone())
@@ -269,6 +302,7 @@
        //保存跑腿人员
        Courier courier1 = new Courier();
        BeanUtils.copyProperties(addCourierDTO, courier1);
        courier1.setCreateTime(LocalDateTime.now());
        this.save(courier1);
        //绑定小区
        if (addCourierDTO.getCommunityId() != null) {
@@ -277,6 +311,8 @@
            communityCourier.setCourierId(courier1.getId());
            communityCourierMapper.insert(communityCourier);
        }
        appUser.setCourierId(courier1.getId());
        appUserService.saveOrUpdate(appUser);
    }
    @Override
@@ -288,7 +324,7 @@
        }
        //是否更改了手机号
        if (!courier.getPhone().equals(editCourierDTO.getPhone())) {
            //更改了手机号
            /*//更改了手机号
            AppUser appUser = appUserMapper.selectOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, editCourierDTO.getPhone()).
                    eq(AppUser::getDelFlag, DelFlagConstant.UNDELETE));
            if (appUser == null) {
@@ -298,18 +334,22 @@
                    .eq(Courier::getDelFlag, DelFlagConstant.UNDELETE));
            if (courier1 != null ) {
                throw new ServiceException("该手机号的跑腿员已存在");
            }
            }*/
            throw new ServiceException("不能修该手机号");
        }
        //是否更改了小区
        CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>().eq(CommunityCourier::getCourierId, editCourierDTO.getId()));
        if (communityCourier != null) {
            //之前有绑定小区
            if (editCourierDTO.getCommunityId() == null) {
                //现在没有绑定,之前的要解绑
                //现在没有绑定
                extracted(courier.getId(), "该跑腿员还有订单未完成,无法变更小区");
                //解绑之前的
                communityCourierMapper.deleteById(communityCourier.getId());
            }else if (!editCourierDTO.getCommunityId().equals(communityCourier.getCommunityId())) {
                //现在绑定了,不和之前的一样
                extracted(courier.getId(), "该跑腿员还有订单未完成,无法变更小区");
                //绑定的小区是否存在
                Community community = communityMapper.selectById(editCourierDTO.getCommunityId());
                if (community == null|| Objects.equals(community.getDelFlag(), DelFlagConstant.DELETE)) {
@@ -323,8 +363,29 @@
                }
                //修改
                communityCourier.setCommunityId(editCourierDTO.getCommunityId());
                communityCourier.setCourierId(editCourierDTO.getId());
                communityCourier.setUpdateTime(LocalDateTime.now());
                communityCourierMapper.updateById(communityCourier);
            }
        }else {
            //之前没绑定 现在绑定
            if (editCourierDTO.getCommunityId() != null) {
                Community community = communityMapper.selectById(editCourierDTO.getCommunityId());
                if (community == null|| Objects.equals(community.getDelFlag(), DelFlagConstant.DELETE)) {
                    throw new ServiceException("绑定的小区不存在");
                }
                //绑定的小区是否被别人绑定了
                CommunityCourier communityCourier1 = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>()
                        .eq(CommunityCourier::getCommunityId, editCourierDTO.getCommunityId()));
                if (communityCourier1 != null) {
                    throw new ServiceException("该小区已被绑定");
                }
                //修改
                communityCourier = new CommunityCourier();
                communityCourier.setCommunityId(editCourierDTO.getCommunityId());
                communityCourier.setCourierId(editCourierDTO.getId());
                communityCourier.setUpdateTime(LocalDateTime.now());
                communityCourierMapper.insert(communityCourier);
            }
        }
        //修改
@@ -333,11 +394,27 @@
    }
    private void extracted(Integer courier, String message) {
        //判断该小区订单是否完成
        Long count = orderMapper.selectCount(new LambdaUpdateWrapper<Order>()
                .eq(Order::getCourierId, courier)
                .eq(Order::getPayStatus, 2)
                .eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
                .eq(Order::getOrderStatus, 2));
        if (count > 0) {
            throw new ServiceException(message);
        }
    }
    @Override
    public void froze(Integer id) {
        Courier  courier= this.getById(id);
        if (courier == null||courier.getDelFlag().equals(DelFlagConstant.DELETE)) {
            throw new ServiceException("该跑腿员不存在");
        }
        //如果是离职,判断是否还有订单在进行中
        if (courier.getStatus().equals(1)){
            extracted(id, "该跑腿员还有订单未完成,无法离职");
        }
        courier.setStatus(courier.getStatus()==0?1:0);
        courier.setUpdateTime(LocalDateTime.now());
@@ -350,11 +427,24 @@
        if (courier == null||courier.getDelFlag().equals(DelFlagConstant.DELETE)) {
            throw new ServiceException("该跑腿员不存在");
        }
        //判断是否还有订单在进行中
        extracted(id, "该跑腿员还有订单未完成,无法注销");
        //判断跑腿员是否绑定了小区
        CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>().eq(CommunityCourier::getCourierId, id));
        if (communityCourier != null) {
            communityCourierMapper.deleteById(communityCourier.getId());//解绑
        }
        //判断用户是否存在,删除用户中跑腿员的信息
        AppUser appUser = appUserMapper.selectOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getCourierId, id).eq(AppUser::getDelFlag, DelFlagConstant.UNDELETE));
        UpdateWrapper<AppUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", appUser.getId())
                .set("courier_id", null);
        appUserMapper.update(null, updateWrapper);
        //删除跑腿员
        courier.setDelFlag(DelFlagConstant.DELETE);
        courier.setUpdateTime(LocalDateTime.now());
        this.updateById(courier);
@@ -370,9 +460,9 @@
    private static long countByTimeRange(List<Order> orderList, LocalDateTime start, LocalDateTime end) {
        return orderList.stream()
                .filter(order -> order.getOrderTime() != null) // 过滤空时间
                .filter(order -> order.getOrderTime().isAfter(start.minusNanos(1))) // 大于等于 start
                .filter(order -> order.getOrderTime().isBefore(end.plusNanos(1))) // 小于等于 end
                .filter(order -> order.getReceivingTime() != null) // 过滤空时间
                .filter(order -> order.getReceivingTime().isAfter(start.minusNanos(1))) // 大于等于 start
                .filter(order -> order.getReceivingTime().isBefore(end.plusNanos(1))) // 小于等于 end
                .count();
    }
pt-errand/src/main/java/com/ruoyi/errand/service/impl/EvaluationServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.errand.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.errand.constant.DelFlagConstant;
@@ -10,6 +11,7 @@
import com.ruoyi.errand.mapper.OrderMapper;
import com.ruoyi.errand.object.dto.app.AddEvaluationDTO;
import com.ruoyi.errand.service.EvaluationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@@ -19,6 +21,7 @@
@Service
public class EvaluationServiceImpl extends ServiceImpl<EvaluationMapper, Evaluation> implements EvaluationService {
    @Autowired
    private  OrderMapper orderMapper;
    @Override
@@ -47,6 +50,14 @@
        }else {
            throw new ServiceException("评价类型错误");
        }
        //查看订单是否评价过
        LambdaQueryWrapper<Evaluation> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Evaluation::getType, addEvaluationDTO.getType());
        lambdaQueryWrapper.eq(Evaluation::getOrderId,addEvaluationDTO.getOrderId());
        Evaluation one = this.getOne(lambdaQueryWrapper);
        if (one!=null){
            throw new ServiceException("该订单已评价过,请去修改");
        }
        Evaluation evaluation = new Evaluation();
        evaluation.setOrderId(addEvaluationDTO.getOrderId());
        evaluation.setType(addEvaluationDTO.getType());
@@ -55,4 +66,16 @@
        evaluation.setCreateTime(LocalDateTime.now());
        this.save(evaluation);
    }
    @Override
    public void edit(AddEvaluationDTO addEvaluationDTO) {
        Evaluation evaluation = this.getById(addEvaluationDTO.getEvaluationId());
        if (evaluation==null){
            throw new ServiceException("该评价不存在");
        }
        evaluation.setRating(addEvaluationDTO.getRating());
        evaluation.setContent(addEvaluationDTO.getContent());
        evaluation.setUpdateTime(LocalDateTime.now());
        this.updateById(evaluation);
    }
}
pt-errand/src/main/java/com/ruoyi/errand/service/impl/FeedbackServiceImpl.java
@@ -12,6 +12,7 @@
import com.ruoyi.errand.domain.AppUser;
import com.ruoyi.errand.domain.Feedback;
import com.ruoyi.errand.mapper.FeedbackMapper;
import com.ruoyi.errand.object.dto.app.AddFeedbackDTO;
import com.ruoyi.errand.object.dto.sys.FeedbackPageListDTO;
import com.ruoyi.errand.object.vo.sys.BannerPageListVO;
import com.ruoyi.errand.object.vo.sys.FeedbackPageListVO;
@@ -19,18 +20,21 @@
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service
public class FeedbackServiceImpl extends ServiceImpl<FeedbackMapper, Feedback> implements FeedbackService {
    @Override
    public void add(String content) {
    public void add(AddFeedbackDTO dto) {
        Feedback feedback = new Feedback();
        feedback.setContent(content);
        feedback.setContent(dto.getContent());
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        feedback.setAppUserId(appuser.getId());
        feedback.setName(appuser.getName());
        feedback.setPhone(appuser.getPhone());
        feedback.setStatus(StatusConstant.UN_DISPOSE);
        feedback.setCreateTime(LocalDateTime.now());
        this.save(feedback);
    }
@@ -60,6 +64,7 @@
        feedback.setStatus(StatusConstant.DISPOSE);
        LoginUser loginUser  = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        feedback.setHandlerId(loginUser.getUserId());
        feedback.setHandleTime(LocalDateTime.now());
        this.updateById(feedback);
    }
}
pt-errand/src/main/java/com/ruoyi/errand/service/impl/OrderServiceImpl.java
@@ -33,12 +33,17 @@
import com.ruoyi.errand.object.vo.sys.UserStatsVO;
import com.ruoyi.errand.service.OrderService;
import com.ruoyi.errand.utils.*;
import com.ruoyi.errand.utils.sms.AliyunSmsService;
import com.ruoyi.errand.utils.wx.PayResult;
import com.ruoyi.errand.utils.wx.RefundCallbackResult;
import com.ruoyi.errand.utils.wx.WechatPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
@@ -67,11 +72,16 @@
    @Resource
    private DeliveryWebSocket deliveryWebSocket;
    @Autowired
    private WechatPayService wechatPayService;
    @Override
    public ConfirmOrderVO confirmOrder(ConfirmOrderDTO confirmOrderDTO) {
        ConfirmOrderVO confirmOrderVO = new ConfirmOrderVO();
        BeanUtils.copyProperties(confirmOrderDTO, confirmOrderVO);
        //小区是否存在
        Community community = communityMapper.selectById(confirmOrderDTO.getCommodityId());
@@ -83,6 +93,10 @@
        }
        //将地址簿信息查询出来
        AddressBook addressBook = addressBookMapper.selectById(confirmOrderDTO.getAddressBookId());
        //地址簿是否存在
        if (addressBook==null||addressBook.getDelFlag().equals(DelFlagConstant.DELETE)){
            throw new ServiceException("地址簿不存在");
        }
        confirmOrderVO.setRecipientName(addressBook.getRecipientName());
        confirmOrderVO.setRecipientPhone(addressBook.getRecipientPhone());
        confirmOrderVO.setAddressDetail(addressBook.getAddressDetail());
@@ -101,7 +115,7 @@
        }else if (confirmOrderDTO.getPayMethod()==1){
            confirmOrderVO.setPayMethod(1);
            //会员支付
            if (appuser.getEndTime().isAfter(LocalDateTime.now())) {
            if (appuser.getEndTime().isBefore(LocalDateTime.now())) {
                //过期了
                throw new ServiceException("支付错误:会员已到期");
            }
@@ -118,6 +132,7 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R orderPayment(ConfirmOrderDTO confirmOrderDTO) {
        Order order = new Order();
        BeanUtils.copyProperties(confirmOrderDTO, order);
@@ -134,6 +149,10 @@
        //将地址簿信息查询出来
        AddressBook addressBook = addressBookMapper.selectById(confirmOrderDTO.getAddressBookId());
        //地址簿是否存在
        if (addressBook==null||addressBook.getDelFlag().equals(DelFlagConstant.DELETE)){
            throw new ServiceException("地址簿不存在");
        }
        order.setRecipientName(addressBook.getRecipientName());
        order.setRecipientPhone(addressBook.getRecipientPhone());
        order.setAddressDetail(addressBook.getAddressDetail());
@@ -177,18 +196,23 @@
        if ( BigDecimal.ZERO.compareTo(paymentMoney) < 0){
            //调起微信支付
            String agencyMatters = order.getAgencyMatters();
            UniPayResult uniPayResult = PaymentUtil.uniPay(order.getOrderNumber(), paymentMoney.doubleValue(),  "代办事项",
                    agencyMatters, "", "/app/order/orderPaymentCallback", appuser.getWxOpenid(), null);
            if(null == uniPayResult || !"100".equals(uniPayResult.getRa_Code())){
                return R.fail(null == uniPayResult ? "支付失败" : uniPayResult.getRb_CodeMsg());
            try {
                R r = wechatPayService.unifiedOrder(order.getId().toString(), order.getOrderNumber(), paymentMoney.toString(), agencyMatters,appuser.getWxOpenid(),"/app/order/orderPaymentCallback");
                if (null == r || 200 != r.getCode()){
                    //支付失败 删除订单
                    order.setDelFlag(1);
                    this.updateById(order);
                    //返回报错信息
                    return R.fail(null == r ? "支付失败" : r.getMsg());
                }
                //将支付数据添加到redis队列中,便于定时任务去校验是否完成支付,没有完成支付支付,15分钟后关闭订单。
                long second = LocalDateTime.now().plusMinutes(15).toEpochSecond(ZoneOffset.UTC);
                redisTemplate.opsForZSet().add("OrderPayment", order.getOrderNumber(), second);
                return r;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            String rc_result = uniPayResult.getRc_Result();
            JSONObject jsonObject = JSON.parseObject(rc_result);
            jsonObject.put("orderId", order.getId().toString());
            //将支付数据添加到redis队列中,便于定时任务去校验是否完成支付,没有完成支付支付,15分钟后关闭订单。
            long second = LocalDateTime.now().plusMinutes(15).toEpochSecond(ZoneOffset.UTC);
            redisTemplate.opsForZSet().add("OrderPayment", order.getOrderNumber(), second);
            return R.ok(jsonObject.toJSONString());
        }
        //会员支付或支付金额为0直接支付成功
@@ -197,11 +221,17 @@
        order.setOrderTime(LocalDateTime.now());//下单时间
        this.updateById(order);
        Map<String,Object> courier= appUserMapper.getCourierByCommunityId(order.getCommunityId());
        if (courier == null || courier.isEmpty()) {
        if (courier == null || courier.isEmpty() ||null == courier.get("id")  ) {
            log.warn("未找到社区ID={}对应的骑手", order.getCommunityId());
            return R.ok();
        }
        //todo 短信通知
        if (courier.get("status").equals("0")){
            log.warn("当前社区骑手离职中,骑手id={}", courier.get("courierId"));
            return R.ok();
        }
        Integer courierIdLong = (Integer) courier.get("courierId");
        order.setCourierId(courierIdLong);
        this.updateById(order);
        sendSmsNotificationToCourier(courier,order);
        //小程序弹窗通知
        notifyDeliveryPerson((Long) courier.get("id"), order,1);//1=新订单
@@ -222,8 +252,7 @@
                return;
            }
//            String content = String.format("您有新的跑腿订单(订单号:%s),请及时处理!", order.getOrderNumber());
            //todo  调用短信服务API
//            SMSUtil.sendSms(order.getOrderNumber(),phoneNumber, "", "");
            AliyunSmsService.sendOrderRemindSms(phoneNumber);
            log.info("已发送短信通知给骑手: {}", phoneNumber);
        } catch (Exception e) {
            log.error("发送短信通知失败", e);
@@ -242,15 +271,15 @@
    }
    @Override
    public R orderPaymentCallback(UniPayCallbackResult uniPayCallbackResult) {
        Order order = this.getBaseMapper().selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, uniPayCallbackResult.getR2_OrderNo()));
    public R orderPaymentCallback(PayResult payResult) {
        Order order = this.getBaseMapper().selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, payResult.getOrderNumber()));
        if(null == order || order.getPayStatus() == 2){
            return R.ok();
        }
        order.setOrderStatus(1);//待确认
        order.setPayStatus(2);//已支付
        order.setOrderTime(LocalDateTime.now());//下单时间
        String r7TrxNo = uniPayCallbackResult.getR9_BankTrxNo();
        String r7TrxNo = payResult.getTransactionId();
        order.setSerialNumber(r7TrxNo);
        this.updateById(order);
@@ -259,7 +288,14 @@
            log.warn("未找到社区ID={}对应的骑手", order.getCommunityId());
            return R.ok();
        }
        //todo 短信通知
        if (courier.get("status").equals("0")){
            log.warn("当前社区骑手离职中,骑手id={}", courier.get("courierId"));
            return R.ok();
        }
        Integer courierIdLong = (Integer) courier.get("courierId");
        order.setCourierId(courierIdLong);
        this.updateById(order);
        sendSmsNotificationToCourier(courier,order);
        //小程序弹窗通知
        notifyDeliveryPerson((Long) courier.get("id"), order,1);//1=新订单
@@ -283,11 +319,11 @@
                    continue;
                }
                //开始执行关闭订单操作
                CloseOrderResult closeOrderResult = PaymentUtil.closeOrder(order.getOrderNumber());
                if((null == closeOrderResult || !closeOrderResult.getRa_Status().equals("100")) &&
                        Arrays.asList("0", "4", "101", "10080000", "10080002", "10083004", "10083005").contains(closeOrderResult.getRb_Code())){
                //开始执行关闭订单操作
                Map<String, String> map = wechatPayService.closeOrder(order.getOrderNumber());
                if((null == map || !map.get("return_code").equals("SUCCESS"))){
                    redisTemplate.opsForZSet().add("OrderPayment", order.getOrderNumber(), 0);
                    log.error("关闭订单失败:{}---->{}", order.getOrderNumber(), JSON.toJSONString(closeOrderResult));
                    log.error("关闭订单失败:{}---->{}", order.getOrderNumber(), map.get("return_msg"));
                }
                redisTemplate.opsForZSet().remove("OrderPayment", order.getOrderNumber());
                //删除订单
@@ -320,13 +356,13 @@
                ||!Objects.equals(order.getAppUserId(), appuser.getId())){
            throw new ServiceException("订单id错误");
        }
        if (order.getOrderStatus()!=1){
        if (order.getOrderStatus()!=1 && order.getOrderStatus()!=2){
            throw new ServiceException("订单状态错误");
        }
        //判断地址簿id是否存在
        if (setConfirmOrderDTO.getAddressBookId()!=null){
            AddressBook addressBook = addressBookMapper.selectById(setConfirmOrderDTO.getAddressBookId());
            if (addressBook==null||addressBook.getDel_flag().equals(DelFlagConstant.DELETE)){
            if (addressBook==null||addressBook.getDelFlag().equals(DelFlagConstant.DELETE)){
                throw new ServiceException("该地址簿id不存在");
            }
            if (!Objects.equals(addressBook.getCommunityId(), order.getCommunityId())){
@@ -392,13 +428,16 @@
    }
    @Override
    public R refundPayMoneyCallback(RefundCallbackResult refundCallbackResult) {
        String code = refundCallbackResult.getR3_RefundOrderNo().substring(1);
        Order order = this.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, code));
    public R refundPayMoneyCallback(String xmlData) {
        RefundCallbackResult result = wechatPayService.processRefundCallback(xmlData);
        if (!result.isSuccess()) {
            return R.fail(result.getMsg());
        }
        Order order = this.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, result.getOrderNo()));
        if (null == order || order.getPayStatus() == 1 || order.getOrderStatus() == 6) {
            return R.ok();
        }
        order.setRefundCode(refundCallbackResult.getR5_RefundTrxNo());
        order.setRefundCode(result.getRefundNo());
        order.setRefundStatus(2);
        order.setRefundTime(LocalDateTime.now());
        this.updateById(order);
@@ -411,7 +450,7 @@
        OrderTopInfoVO orderTopInfoVO = new OrderTopInfoVO();
        //总金额
        Map<String, Object> total = this.baseMapper.getOrderTopInfoByDate(communityId,null,null);
        orderTopInfoVO.setTodayOrderNum(Integer.valueOf(String.valueOf(total.get("num"))) );
        orderTopInfoVO.setTotalOrderNum(Integer.valueOf(String.valueOf(total.get("num"))) );
        orderTopInfoVO.setTotalOrderAmount(new BigDecimal(String.valueOf(total.get("amount"))));
        //今日
@@ -467,6 +506,7 @@
    public IPage<FinanceStatisticsVO> financeStatistics(FinanceStatisticsDTO dto) {
        //查询出总的数量
        IPage<FinanceStatisticsVO> page = new Page<>();
        dto.setPageNum(Math.max(dto.getPageNum() - 1, 0)*dto.getPageSize());
        page.setTotal(this.getBaseMapper().selectPageTotal(dto));
        List<FinanceStatisticsVO> list=this.getBaseMapper().financeStatistics(dto);
        page.setRecords(list);
@@ -584,14 +624,17 @@
     */
    public R refundPayMoney(Order order) {
        //开始退款
        BigDecimal paymentAmount = order.getPaymentAmount();
        if (BigDecimal.ZERO.compareTo(order.getPaymentAmount()) < 0) {//支付的金额是否大于0
            //微信退款
            RefundResult refund = PaymentUtil.refund(order.getOrderNumber(), "R" + order.getOrderNumber(), paymentAmount.doubleValue(),
                    "/app/order/refundPayMoneyCallback");
            if (!"100".equals(refund.getRa_Status())) {
                return R.fail(refund.getRc_CodeMsg());//退款失败
            Map<String,String> map = wechatPayService.refund(order.getOrderNumber(), order.getOrderNumber(), order.getPaymentAmount().toString(), order.getPaymentAmount().toString(), "退款", "/order/refundPayMoneyCallback");
            if (!"SUCCESS".equals(map.get("return_code"))) {
                return R.fail(map.get("return_msg"));//退款失败
            }
            //这里申请成功后先返回
            order.setRefundStatus(1);
            this.updateById(order);
            return R.ok();
        }
        return R.ok();
    }
pt-errand/src/main/java/com/ruoyi/errand/service/impl/PhoneServiceImpl.java
@@ -24,20 +24,22 @@
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //查找小区客服
        Phone phone = this.getBaseMapper().selectOne(new LambdaUpdateWrapper<Phone>().eq(Phone::getType, 2)
                .eq(Phone::getCommunity_id, appuser.getCommunityId()));
                .eq(Phone::getCommunityId, appuser.getCommunityId()));
        if (phone!=null){
            return phone.getPhone();
        }
        //查找平台客服
        List<Phone> list = this.getBaseMapper().selectList(new LambdaUpdateWrapper<Phone>().eq(Phone::getType, 1));
        if (list.size()>0){}
        return list.get(0).getPhone();
    }
    @Override
    public void saveServicePhone(String phone) {
        Phone phoneEntity = this.getBaseMapper().selectOne(new LambdaUpdateWrapper<Phone>().eq(Phone::getType, 1));
        if (phoneEntity!=null){
        if (phoneEntity==null){
            //不存在
            phoneEntity = new Phone();
            phoneEntity.setType(1);
            phoneEntity.setPhone(phone);
            this.save(phoneEntity);
pt-errand/src/main/java/com/ruoyi/errand/service/impl/ReportServiceImpl.java
@@ -10,6 +10,7 @@
import com.ruoyi.errand.domain.AppUser;
import com.ruoyi.errand.domain.Report;
import com.ruoyi.errand.mapper.ReportMapper;
import com.ruoyi.errand.object.dto.app.AddRegisterReportDTO;
import com.ruoyi.errand.object.dto.app.AddReportDTO;
import com.ruoyi.errand.object.dto.sys.ReportPageListDTO;
import com.ruoyi.errand.object.vo.sys.CourierPageListVO;
@@ -26,11 +27,14 @@
    @Override
    public void add(AddReportDTO addReportDTO) {
        AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Report report = new Report();
        BeanUtils.copyProperties(addReportDTO,report);
        report.setAppUserId(appUser.getId());
        report.setRegionId(addReportDTO.getRegionId());
        report.setCommunityName(addReportDTO.getCommunityName());
        report.setAddressDetail(addReportDTO.getAddressDetail());
        report.setPhone(addReportDTO.getPhone());
        report.setUsername(addReportDTO.getUsername());
        report.setStatus(StatusConstant.UN_DISPOSE);
        report.setCreateTime(LocalDateTime.now());
        this.save(report);
    }
pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipOrderServiceImpl.java
@@ -14,11 +14,14 @@
import com.ruoyi.errand.mapper.VipOrderMapper;
import com.ruoyi.errand.mapper.VipSettingMapper;
import com.ruoyi.errand.object.dto.app.VipPaymentDTO;
import com.ruoyi.errand.object.vo.sys.OrderSysDetailVO;
import com.ruoyi.errand.service.VipOrderService;
import com.ruoyi.errand.utils.CloseOrderResult;
import com.ruoyi.errand.utils.PaymentUtil;
import com.ruoyi.errand.utils.UniPayCallbackResult;
import com.ruoyi.errand.utils.UniPayResult;
import com.ruoyi.errand.utils.wx.PayResult;
import com.ruoyi.errand.utils.wx.WechatPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -29,10 +32,7 @@
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.*;
@Service
@Slf4j
@@ -43,6 +43,8 @@
    private RedisTemplate redisTemplate;
    @Resource
    private AppUserMapper appUserMapper;
    @Resource
    private WechatPayService wechatPayService;
    @Override
    public R vipPayment(VipPaymentDTO vipPaymentDTO) {
@@ -51,8 +53,8 @@
        vipOrder.setAppUserId(appuser.getId());
        VipSetting vipSetting = vipSettingMapper.selectById(vipPaymentDTO.getId());
        vipOrder.setOrderAmount(vipSetting.getVip_price());
        vipOrder.setPaymentAmount(vipSetting.getVip_price());
        vipOrder.setOrderAmount(vipSetting.getVipPrice());
        vipOrder.setPaymentAmount(vipSetting.getVipPrice());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        vipOrder.setOrderNumber("QJS" + getNumber(3) + sdf.format(new Date()));
        vipOrder.setPayStatus(1);
@@ -62,23 +64,28 @@
        BigDecimal paymentMoney = vipOrder.getOrderAmount();
        if ( BigDecimal.ZERO.compareTo(paymentMoney) < 0){
            //调起微信支付
            String vipName = vipSetting.getVip_name();
            UniPayResult uniPayResult = PaymentUtil.uniPay(vipOrder.getOrderNumber(), paymentMoney.doubleValue(),  "购买会员",
                    vipName, "", "/app/vipOrder/orderPaymentCallback", appuser.getWxOpenid(), null);
            if(null == uniPayResult || !"100".equals(uniPayResult.getRa_Code())){
                return R.fail(null == uniPayResult ? "支付失败" : uniPayResult.getRb_CodeMsg());
            String vipName = vipSetting.getVipName();
            try {
                R r = wechatPayService.unifiedOrder(vipOrder.getId().toString(), vipOrder.getOrderNumber(), paymentMoney.toString(), "购买"+vipName,appuser.getWxOpenid(),"/app/vipOrder/orderPaymentCallback");
                if (null == r || 200 != r.getCode()) {
                    //支付失败 删除订单
                    vipOrder.setDelFlag(1);
                    this.updateById(vipOrder);
                    //返回报错信息
                    return R.fail(null == r ? "支付失败" : r.getMsg());
                }
                //将支付数据添加到redis队列中,便于定时任务去校验是否完成支付,没有完成支付支付,15分钟后关闭订单。
                long second = LocalDateTime.now().plusMinutes(15).toEpochSecond(ZoneOffset.UTC);
                redisTemplate.opsForZSet().add("VipOrderPayment", vipOrder.getOrderNumber(), second);
                return r;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            String rc_result = uniPayResult.getRc_Result();
            JSONObject jsonObject = JSON.parseObject(rc_result);
            jsonObject.put("orderId", vipOrder.getId().toString());
            //将支付数据添加到redis队列中,便于定时任务去校验是否完成支付,没有完成支付支付,15分钟后关闭订单。
            long second = LocalDateTime.now().plusMinutes(15).toEpochSecond(ZoneOffset.UTC);
            redisTemplate.opsForZSet().add("VipOrderPayment", vipOrder.getOrderNumber(), second);
            return R.ok(jsonObject.toJSONString());
        }
        //设置vipOrder信息
        vipOrder.setPayStatus(2);//已支付
        vipOrder.setOrderTime(LocalDateTime.now());//下单时间
        vipOrder.setOrderStatus(4);
        this.updateById(vipOrder);
        //更新用户信息
        Long appUserId = vipOrder.getAppUserId();
@@ -96,16 +103,17 @@
    }
    @Override
    public R orderPaymentCallback(UniPayCallbackResult uniPayCallbackResult) {
        VipOrder vipOrder = this.getBaseMapper().selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber, uniPayCallbackResult.getR2_OrderNo()));
    public R orderPaymentCallback(PayResult payResult) {
        VipOrder vipOrder = this.getBaseMapper().selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber, payResult.getOrderNumber()));
        if(null == vipOrder || vipOrder.getPayStatus() == 2){
            return R.ok();
        }
        //设置vipOrder信息
        vipOrder.setPayStatus(2);//已支付
        vipOrder.setOrderTime(LocalDateTime.now());//下单时间
        String r7TrxNo = uniPayCallbackResult.getR9_BankTrxNo();
        String r7TrxNo = payResult.getTransactionId();
        vipOrder.setSerialNumber(r7TrxNo);
        vipOrder.setOrderStatus(4);
        this.updateById(vipOrder);
        //更新用户信息
        //检查是否续期的
@@ -120,6 +128,7 @@
        // 根据 vipId 计算会员到期时间
        LocalDateTime endTime = calculateEndTime(appUser.getEndTime(), vipOrder.getVipId());
        appUser.setEndTime(endTime);
        appUserMapper.updateById(appUser);
        return R.ok();
    }
@@ -138,11 +147,10 @@
                    continue;
                }
                //开始执行关闭订单操作
                CloseOrderResult closeOrderResult = PaymentUtil.closeOrder(order.getOrderNumber());
                if((null == closeOrderResult || !closeOrderResult.getRa_Status().equals("100")) &&
                        Arrays.asList("0", "4", "101", "10080000", "10080002", "10083004", "10083005").contains(closeOrderResult.getRb_Code())){
                Map<String, String> map = wechatPayService.closeOrder(order.getOrderNumber());
                if((null == map || !map.get("return_code").equals("SUCCESS"))){
                    redisTemplate.opsForZSet().add("VipOrderPayment", order.getOrderNumber(), 0);
                    log.error("关闭订单失败:{}---->{}",order.getOrderNumber(), JSON.toJSONString(closeOrderResult));
                    log.error("关闭订单失败:{}---->{}", order.getOrderNumber(), map.get("return_msg"));
                }
                redisTemplate.opsForZSet().remove("VipOrderPayment", order.getOrderNumber());
                //删除订单
@@ -153,6 +161,12 @@
        }
    }
    @Override
    public OrderSysDetailVO detail(Integer id) {
        return this.getBaseMapper().detail(id);
    }
    private LocalDateTime calculateEndTime(LocalDateTime startTime, Integer vipId) {
        switch (vipId) {
pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipSettingServiceImpl.java
@@ -1,17 +1,26 @@
package com.ruoyi.errand.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.errand.domain.Agreement;
import com.ruoyi.errand.domain.VipSetting;
import com.ruoyi.errand.mapper.VipSettingMapper;
import com.ruoyi.errand.object.dto.app.AgreementDTO;
import com.ruoyi.errand.object.dto.sys.SetPriceDTO;
import com.ruoyi.errand.object.vo.app.VipInfoListVO;
import com.ruoyi.errand.service.AgreementService;
import com.ruoyi.errand.service.VipSettingService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
@Service
public class VipSettingServiceImpl extends ServiceImpl<VipSettingMapper, VipSetting> implements VipSettingService {
    @Resource
    private AgreementService agreementService;
    @Override
    public List<VipInfoListVO> getVipInfoList() {
@@ -20,21 +29,45 @@
    @Override
    public void setPrice(SetPriceDTO setPriceDTO) {
        VipSetting byId = this.getById(setPriceDTO.getId());
        if (byId == null) {
            byId=new VipSetting();
            byId.setId(setPriceDTO.getId());
            if (setPriceDTO.getId()==1) byId.setVip_name("月卡会员");
            if (setPriceDTO.getId()==2) byId.setVip_name("季卡会员");
            if (setPriceDTO.getId()==3) byId.setVip_name("半年卡会员");
            if (setPriceDTO.getId()==4) byId.setVip_name("年卡会员");
            byId.setVip_price(setPriceDTO.getVip_price());
            this.save(byId);
        }else {
            byId.setVip_price(setPriceDTO.getVip_price());
            this.updateById(byId);
        List<VipSetting> vipSettings = this.baseMapper.selectList(new LambdaQueryWrapper<VipSetting>().in(VipSetting::getId, Arrays.asList(1, 2, 3, 4)));
        vipSettings.forEach(vipSetting -> {
            if (vipSetting.getId()==1) vipSetting.setVipPrice(setPriceDTO.getVipPriceOne());
            if (vipSetting.getId()==2) vipSetting.setVipPrice(setPriceDTO.getVipPriceTwo());
            if (vipSetting.getId()==3) vipSetting.setVipPrice(setPriceDTO.getVipPriceThree());
            if (vipSetting.getId()==4) vipSetting.setVipPrice(setPriceDTO.getVipPriceFour());
        });
        this.updateBatchById(vipSettings);
        //设置会员协议
        Agreement one = agreementService.getOne(new LambdaQueryWrapper<Agreement>().eq(Agreement::getType,8));
        if (one!=null){
            agreementService.removeById(one);
        }
        Agreement agreement = new Agreement();
        agreement.setType(8);
        agreement.setContent(setPriceDTO.getContent());
        agreementService.save(agreement);
    }
    @Override
    public SetPriceDTO getPrice() {
        SetPriceDTO setPriceDTO = new SetPriceDTO();
        List<VipSetting> vipSettings = this.baseMapper.selectList(new LambdaQueryWrapper<VipSetting>().in(VipSetting::getId, Arrays.asList(1, 2, 3, 4)));
        vipSettings.forEach(vipSetting -> {
            if (vipSetting.getId()==1) setPriceDTO.setVipPriceOne(vipSetting.getVipPrice());
            if (vipSetting.getId()==2) setPriceDTO.setVipPriceTwo(vipSetting.getVipPrice());
            if (vipSetting.getId()==3) setPriceDTO.setVipPriceThree(vipSetting.getVipPrice());
            if (vipSetting.getId()==4) setPriceDTO.setVipPriceFour(vipSetting.getVipPrice());
        });
        //会员协议
        Agreement one = agreementService.getOne(new LambdaQueryWrapper<Agreement>().eq(Agreement::getType,8));
        if (one!=null){
            setPriceDTO.setContent(one.getContent());
        }
        return setPriceDTO;
    }
}
pt-errand/src/main/java/com/ruoyi/errand/utils/SMSUtil.java
@@ -42,12 +42,12 @@
        try {
            //必填,请参考"开发准备"获取如下数据,替换为实际值
            String url = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1"; //APP接入地址+接口访问URI
            String appKey = ""; //todo APP_Key
            String appSecret = ""; //APP_Secret
            String appKey = "wxedd7aefdfaf897cf"; //todo APP_Key
            String appSecret = "e1a8dba539294da6b935e8f0f3b09aac"; //APP_Secret
            
            //条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
            //国际/港澳台短信不用关注该参数
            String signature = "社区代办"; //签名名称
            String signature = "玮儿科技"; //签名名称
            
            //必填,全局号码格式(包含国家码),示例:+8615123456789,多个号码之间用英文逗号分隔
            String receiver = "+86" + phone; //短信接收人号码
pt-errand/src/main/java/com/ruoyi/errand/utils/WXCore.java
@@ -7,7 +7,7 @@
    private static final String WATERMARK = "watermark";
    @Value("${wx.appletsAppid}")
    @Value("${wx.appid}")
    private static String appid ;
pt-errand/src/main/java/com/ruoyi/errand/utils/WeChatUtil.java
@@ -33,7 +33,7 @@
@Component
public class WeChatUtil {
    @Value("${wx.appletsAppid}")
    @Value("${wx.appid}")
    private String wxAppletsAppid;
    @Value("${wx.appletsAppSecret}")
pt-errand/src/main/java/com/ruoyi/errand/utils/sms/AliyunSmsService.java
New file
@@ -0,0 +1,142 @@
package com.ruoyi.errand.utils.sms;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.springframework.stereotype.Service;
public class AliyunSmsService {
    // 阿里云短信服务配置
    private static final String ACCESS_KEY_ID = "LTAI5tRtwxPMw8aohbLLcjjo";
    private static final String ACCESS_KEY_SECRET = "NSKeley8OjCsl7AQJnDKxPIh1dIaOu";
    private static final String SIGN_NAME = "玮儿科技";
    private static final String TEMPLATE_CODE = "SMS_319401491";
    // 新增跑腿员接单提醒模板 CODE
    private static final String TEMPLATE_CODE_ORDER = "SMS_489100144";
    /**
     * 发送短信验证码
     * @param phoneNumber 手机号码
     * @param code 验证码
     * @return 是否发送成功
     */
    public static boolean sendVerificationCode(String phoneNumber, String code) {
        // 初始化客户端
        DefaultProfile profile = DefaultProfile.getProfile(
            "cn-chengdu",
                ACCESS_KEY_ID,
                ACCESS_KEY_SECRET
        );
        IAcsClient client = new DefaultAcsClient(profile);
        // 构建请求
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        // 设置请求参数
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", phoneNumber);
        request.putQueryParameter("SignName", SIGN_NAME);
        request.putQueryParameter("TemplateCode", TEMPLATE_CODE);
        // 模板参数JSON,根据实际模板调整
        String templateParam = String.format("{\"code\":\"%s\"}", code);
        request.putQueryParameter("TemplateParam", templateParam);
        try {
            // 发送请求并获取响应
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            // 解析响应结果
            return response.getHttpStatus() == 200 &&
                   response.getData().contains("\"Code\":\"OK\"");
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return false;
    }
    /**
     * 生成随机验证码
     * @param length 验证码长度
     * @return 随机验证码
     */
    public static String generateVerificationCode(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append((int)(Math.random() * 10));
        }
        return sb.toString();
    }
    /**
     * 发送跑腿员接单提醒短信
     * @param phoneNumber 跑腿员手机号码
     * @return 是否发送成功
     */
    public static boolean sendOrderRemindSms(String phoneNumber) {
        // 初始化客户端(复用已有的配置)
        DefaultProfile profile = DefaultProfile.getProfile(
                "cn-chengdu",
                ACCESS_KEY_ID,
                ACCESS_KEY_SECRET
        );
        IAcsClient client = new DefaultAcsClient(profile);
        // 构建请求
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        // 设置请求参数
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", phoneNumber);
        request.putQueryParameter("SignName", SIGN_NAME);
        request.putQueryParameter("TemplateCode", TEMPLATE_CODE_ORDER);
        // 该模板无自定义变量,传空 JSON(根据模板实际情况,若有变量需按格式填充)
        request.putQueryParameter("TemplateParam", "{}");
        try {
            // 发送请求并获取响应
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            // 解析响应结果
            return response.getHttpStatus() == 200 &&
                    response.getData().contains("\"Code\":\"OK\"");
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return false;
    }
    public static void main(String[] args) {
      /*  String phoneNumber = "19923261698";
        boolean result = sendVerificationCode(phoneNumber,"123123");
        System.out.println("短信发送结果:" + result);*/
        // 测试发送接单提醒
        String phoneNumberOrder = "19923261698"; // 替换为实际跑腿员手机号
        boolean resultOrder = sendOrderRemindSms(phoneNumberOrder);
        System.out.println("接单提醒短信发送结果:" + resultOrder);
    }
}
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/HttpUtil.java
New file
@@ -0,0 +1,99 @@
package com.ruoyi.errand.utils.wx;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
 * HTTP工具类
 */
public class HttpUtil {
    /**
     * 发送POST请求
     */
    public static String post(String urlStr, String data) throws Exception {
        // 设置超时时间(单位:毫秒)
        int timeout = 5000; // 5秒
        // 发送 POST 请求
        try (HttpResponse response = HttpRequest.post(urlStr)
                .body(data, "application/xml") // 设置 XML 请求体
                .timeout(timeout)
                .execute()) {
            // 检查 HTTP 状态码
            if (!response.isOk()) {
                throw new RuntimeException("HTTP请求失败,状态码: " + response.getStatus()
                        + ", 响应: " + response.body());
            }
            return response.body();
        }
    }
    /**
     * 发送HTTPS请求
     */
    public static String postHttps(String urlStr, String data, String certPath, String certPassword) throws Exception {
        // 创建SSL上下文
        SSLContext sslContext = SSLContext.getInstance("SSL");
        TrustManager[] trustManagers = {new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }};
        sslContext.init(null, trustManagers, new java.security.SecureRandom());
        // 创建HTTPS连接
        URL url = new URL(urlStr);
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setSSLSocketFactory(sslContext.getSocketFactory());
        conn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setUseCaches(false);
        conn.setRequestProperty("Content-Type", "application/xml");
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Charset", "UTF-8");
        // 发送请求
        OutputStream os = conn.getOutputStream();
        os.write(data.getBytes("UTF-8"));
        os.flush();
        os.close();
        // 获取响应
        StringBuilder result = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String line;
        while ((line = br.readLine()) != null) {
            result.append(line);
        }
        br.close();
        return result.toString();
    }
}
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/PayResult.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.errand.utils.wx;
import lombok.Data;
/**
 * 支付结果VO
 */
@Data
public class PayResult {
    // 订单ID
    private String orderNumber;
    // 微信交易ID
    private String transactionId;
    // 支付金额
    private String totalFee;
}
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/RefundCallbackResult.java
New file
@@ -0,0 +1,38 @@
package com.ruoyi.errand.utils.wx;
import lombok.Data;
/**
 * 退款回调结果实体
 */
@Data
public class RefundCallbackResult {
    private boolean success;        // 处理是否成功
    private String msg;             // 结果描述
    private String orderNo;         // 原订单号
    private String refundNo;        // 退款订单号
    private String refundId;        // 微信退款ID
    private String totalFee;        // 原订单金额(分)
    private String refundFee;       // 退款金额(分)
    private String refundStatus;    // 退款状态
    // 成功响应
    public static RefundCallbackResult success() {
        return success("处理成功");
    }
    public static RefundCallbackResult success(String msg) {
        RefundCallbackResult result = new RefundCallbackResult();
        result.setSuccess(true);
        result.setMsg(msg);
        return result;
    }
    // 失败响应
    public static RefundCallbackResult fail(String msg) {
        RefundCallbackResult result = new RefundCallbackResult();
        result.setSuccess(false);
        result.setMsg(msg);
        return result;
    }
}
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/WechatPayConfig.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.errand.utils.wx;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * 微信支付配置类
 */
@Data
@Component
@ConfigurationProperties(prefix = "wx")
public class WechatPayConfig {
    // 小程序APPID
    private String appId;
    // 商户号
    private String mchId;
    // 商户API密钥
    private String key;
    // 支付结果通知地址
    private String callbackPath;
    // 证书路径
    private String certPath;
    // 商户RAS加密公钥路径
    private String RASPath;
    private String wxAppletsAppSecret;
}
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/WechatPayService.java
New file
@@ -0,0 +1,727 @@
package com.ruoyi.errand.utils.wx;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.errand.utils.MD5AndKL;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.RSAPublicKeySpec;
import java.util.*;
/**
 * 微信支付服务类
 */
@Service
public class WechatPayService {
    @Autowired
    private WechatPayConfig wechatPayConfig;
    private static final String RSA_PUBLIC_KEY_FILENAME = "wechat_rsa_public_key.pem";
    private static final String CERT_FOLDER = "cert/";
    /**
     * 统一下单
     * @param orderNumber 订单号
     * @param totalFee 总金额(分)
     * @param body 商品描述
     * @param openid 用户openid
     * @return 预支付订单信息
     */
    public R unifiedOrder(String orderId,String orderNumber, String totalFee, String body, String openid, String callbackPath) throws Exception {
        int i = new BigDecimal(totalFee).multiply(new BigDecimal("100")).intValue();
        String hostAddress = null;
        try {
            hostAddress = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        // 构建请求参数
        Map<String, String> params = new HashMap<>();
        params.put("appid", wechatPayConfig.getAppId());
        params.put("mch_id", wechatPayConfig.getMchId());
        params.put("nonce_str", generateNonceStr());
        params.put("body", body);
        params.put("out_trade_no", orderNumber);
        params.put("total_fee", String.valueOf(i) );
        params.put("spbill_create_ip", "221.182.45.100"); // 实际应用中应获取客户端IP
        params.put("notify_url", wechatPayConfig.getCallbackPath()+callbackPath);
        params.put("trade_type", "JSAPI");
        params.put("openid", openid);
        // 生成签名
        String sign = weixinSignature(params);
        params.put("sign", sign);
        // 将参数转换为XML
        String xmlParams = XMLUtil.mapToXml(params).replaceFirst("^<\\?xml.+?\\?>\\s*", "");
        // 发送请求到微信支付统一下单接口
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String result = HttpUtil.post(url, xmlParams);
        // 解析返回结果
        Map<String, String> resultMap = XMLUtil.xmlToMap(result);
        // 验证签名
        if (!verifySign(resultMap, wechatPayConfig.getKey())) {
            return R.fail("微信支付签名验证失败");
//            throw new Exception("微信支付签名验证失败");
        }
        if (!resultMap.get("return_code").equals("SUCCESS")) {
            return R.fail(resultMap.get("return_msg"));
        }
        // 构建小程序支付所需参数
        Map<String, String> payParams = new HashMap<>();
        payParams.put("appId", wechatPayConfig.getAppId());
        payParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        payParams.put("nonceStr", generateNonceStr());
        payParams.put("package", "prepay_id=" + resultMap.get("prepay_id"));
        payParams.put("signType", "MD5");
        // 生成支付签名
        String paySign = weixinSignature(payParams);
        payParams.put("paySign", paySign);
        //给前端标识
//        payParams.put("payMethod","1");
        payParams.put("orderId", orderId);
        return R.ok(JSON.toJSONString(payParams));
    }
    /**
     * 微信下单的签名算法
     * @param map
     * @return
     */
    private String weixinSignature(Map<String, String> map){
        try {
            Set<Map.Entry<String, String>> entries = map.entrySet();
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(entries);
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (item.getKey() != null || item.getKey() != "") {
                    String key = item.getKey();
                    Object val = item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(key + "=" + val + "&");
                    }
                }
            }
            sb.append("key=" + wechatPayConfig.getKey());
            String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式
            return sign;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 处理支付结果通知
     * @param request HTTP请求
     * @return 处理结果
     */
    public PayResult processNotify(HttpServletRequest request) throws Exception {
        // 读取请求内容
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
        String line;
        StringBuilder xml = new StringBuilder();
        while ((line = br.readLine()) != null) {
            xml.append(line);
        }
        br.close();
        // 解析XML
        Map<String, String> resultMap = XMLUtil.xmlToMap(xml.toString());
        // 验证签名
        if (!verifySign(resultMap, wechatPayConfig.getKey())) {
            throw new Exception("微信支付签名验证失败");
        }
        // 验证支付结果
        if (!"SUCCESS".equals(resultMap.get("return_code")) || !"SUCCESS".equals(resultMap.get("result_code"))) {
            throw new Exception("微信支付结果异常");
        }
        // 处理业务逻辑
        PayResult payResult = new PayResult();
        payResult.setOrderNumber(resultMap.get("out_trade_no"));
        payResult.setTransactionId(resultMap.get("transaction_id"));
        payResult.setTotalFee(resultMap.get("total_fee"));
        return payResult;
    }
    /**
     * 生成随机字符串
     */
    private String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }
    /**
     * 微信支付API V2签名算法
     * @param params 请求参数
     * @param apiKey 商户API密钥
     * @return 签名结果
     */
    public static String generateSign(Map<String, String> params, String apiKey) throws Exception {
        // 1. 过滤空值参数
        Map<String, String> filteredParams = new HashMap<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            // 排除sign字段和空值字段
            if (!"sign".equals(key) && value != null && !value.isEmpty()) {
                filteredParams.put(key, value);
            }
        }
        // 2. 按照ASCII码排序参数名
        List<String> keys = new ArrayList<>(filteredParams.keySet());
        Collections.sort(keys);
        // 3. 构建签名原始字符串
        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            String value = filteredParams.get(key);
            sb.append(key).append("=").append(value).append("&");
        }
        // 4. 添加API密钥
        sb.append("key=").append(apiKey);
        // 5. MD5加密并转为大写
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(sb.toString().getBytes("UTF-8"));
        // 6. 转换为十六进制字符串
        StringBuilder sign = new StringBuilder();
        for (byte b : digest) {
            sign.append(String.format("%02x", b & 0xff));
        }
        return sign.toString().toUpperCase();
    }
    /**
     * 验证签名
     */
    private boolean verifySign(Map<String, String> params, String key) throws Exception {
        String sign = params.get("sign");
        if (StringUtils.isEmpty(sign)) {
            return false;
        }
        // 移除sign字段
        Map<String, String> newParams = new HashMap<>(params);
        newParams.remove("sign");
        // 生成新签名
        String newSign = generateSign(newParams, key);
        return sign.equals(newSign);
    }
    /**
     * 关闭订单
     */
    public Map<String, String> closeOrder(String orderId){
        // 构建请求参数
        Map<String, String> params = new HashMap<>();
        params.put("appid", wechatPayConfig.getAppId());
        params.put("mch_id", wechatPayConfig.getMchId());
        params.put("nonce_str", generateNonceStr());
        params.put("out_trade_no", orderId);
        // 生成签名
        String sign = weixinSignature(params);
        params.put("sign", sign);
        // 将参数转换为XML
        String xmlParams = XMLUtil.mapToXml(params);
        // 发送请求到微信支付关闭订单接口
        String url = "https://api.mch.weixin.qq.com/pay/closeorder";
        String result = null;
        try {
            result = HttpUtil.post(url, xmlParams);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 解析返回结果
        try {
            return XMLUtil.xmlToMap(result);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 查询订单
     */
    public Map<String, String> queryOrder(String orderId) throws Exception {
        // 构建请求参数
        Map<String, String> params = new HashMap<>();
        params.put("appid", wechatPayConfig.getAppId());
        params.put("mch_id", wechatPayConfig.getMchId());
        params.put("nonce_str", generateNonceStr());
        params.put("out_trade_no", orderId);
        // 生成签名
        String sign = generateSign(params, wechatPayConfig.getKey());
        params.put("sign", sign);
        // 将参数转换为XML
        String xmlParams = XMLUtil.mapToXml(params);
        // 发送请求到微信支付查询订单接口
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";
        String result = HttpUtil.post(url, xmlParams);
        // 解析返回结果
        return XMLUtil.xmlToMap(result);
    }
    /**
     * 申请退款 - 使用证书
     */
    public Map<String, String>  refund(String orderNo, String refundNo, String totalFee, String refundFee, String refundDesc,String callbackPath) {
        int i = new BigDecimal(totalFee).multiply(new BigDecimal("100")).intValue();
        int j = new BigDecimal(refundFee).multiply(new BigDecimal("100")).intValue();
        try {
            // 构建请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appid", wechatPayConfig.getAppId());
            params.put("mch_id", wechatPayConfig.getMchId());
            params.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
            params.put("out_trade_no", orderNo);
            params.put("out_refund_no", refundNo);
            params.put("total_fee", String.valueOf(i));
            params.put("refund_fee", String.valueOf(j));
            params.put("refund_desc", refundDesc);
            params.put("notify_url", wechatPayConfig.getCallbackPath() + callbackPath); // 退款结果
            // 生成签名
            String sign = weixinSignature(params);
            params.put("sign", sign);
            // 转换为XML
            String xmlParams = XMLUtil.mapToXml(params);
            // 使用证书发送请求
            String result = postWithCert("https://api.mch.weixin.qq.com/secapi/pay/refund", xmlParams);
            // 解析结果
            Map<String, String> resultMap = XMLUtil.xmlToMap(result);
            System.out.println("申请退款结果"+resultMap);
            // 验证签名
            if (!verifySign(resultMap, wechatPayConfig.getKey())) {
                resultMap.put("return_code","FAILED");
                resultMap.put("return_msg","申请退款结果签名验证失败");
                return resultMap;
            }
            return resultMap;
        } catch (Exception e) {
            Map<String, String> resultMap=new HashMap<>();
            resultMap.put("return_code","FAILED");
            resultMap.put("return_msg","申请退款失败");
            return resultMap;
        }
    }
    /**
     * 使用证书发送请求
     */
    private String postWithCert(String url, String xmlData) throws Exception {
        // 证书类型为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 获取证书路径
        String certPath = wechatPayConfig.getCertPath();
        // 如果是classpath路径,使用ClassLoader加载
        if (certPath.startsWith("classpath:")) {
            String path = certPath.substring("classpath:".length());
            try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path)) {
                if (inputStream == null) {
                    throw new FileNotFoundException("证书文件不存在: " + path);
                }
                keyStore.load(inputStream, wechatPayConfig.getMchId().toCharArray());
            }
        } else {
            // 传统文件路径
            try (FileInputStream inputStream = new FileInputStream(new File(certPath))) {
                keyStore.load(inputStream, wechatPayConfig.getMchId().toCharArray());
            }
        }
        // 实例化密钥库 & 初始化密钥工厂
        SSLContext sslContext = SSLContext.getInstance("TLS");
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, wechatPayConfig.getMchId().toCharArray());
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
        // 创建HttpsURLConnection对象
        URL httpsUrl = new URL(url);
        HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();
        conn.setSSLSocketFactory(sslContext.getSocketFactory());
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        // 发送请求
        OutputStream outputStream = conn.getOutputStream();
        outputStream.write(xmlData.getBytes("UTF-8"));
        outputStream.flush();
        outputStream.close();
        // 获取响应
        InputStream inputStream = conn.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        StringBuilder result = new StringBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            result.append(line);
        }
        bufferedReader.close();
        inputStream.close();
        conn.disconnect();
        return result.toString();
    }
    /**
     * 处理退款回调
     */
    public RefundCallbackResult processRefundCallback(String xmlData) {
        try {
            // 1. 解析回调XML数据
            if (StringUtils.isEmpty(xmlData)) {
                return RefundCallbackResult.fail("回调数据为空");
            }
            //2.解析参数
            System.out.println(xmlData);
            System.out.println("----------------------------------------");
            Map<String, String> resultMap = XMLUtil.xmlToMap(xmlData);
            System.out.println(resultMap.get("req_info"));
            // 3. 检查返回状态
            String returnCode = resultMap.get("return_code");
            if (!"SUCCESS".equals(returnCode)) {
                String errMsg = resultMap.get("return_msg");
                return RefundCallbackResult.fail("通信失败:" + errMsg);
            }
            //4 使用商户API密钥解密req_info(AES-256-CBC算法)
            String decryptData = decrypt(resultMap.get("req_info"), wechatPayConfig.getKey());
            Map<String, String> refundDetail = XMLUtil.xmlToMap(decryptData);
            // 4. 提取退款信息
            String orderNo = refundDetail.get("out_trade_no");        // 原订单号
            String refundNo = refundDetail.get("out_refund_no");      // 退款订单号
            String refundId = refundDetail.get("refund_id");          // 微信退款ID
            System.err.println("退款回调成功,订单号:"+orderNo+",退款号:"+refundNo+",状态:{}"+refundId);
            RefundCallbackResult refundCallbackResult = RefundCallbackResult.success();
            refundCallbackResult.setOrderNo(orderNo);
            refundCallbackResult.setRefundNo(refundId);
            return refundCallbackResult;
        } catch (Exception e) {
            return RefundCallbackResult.fail("系统异常:" + e.getMessage());
        }
    }
    private static String wxDecrypt(String req_info, String key)  throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException{
        byte[] decode = Base64.getDecoder().decode(req_info);
        System.out.println(Arrays.toString(decode));
        String sign = MD5AndKL.MD5Encode(key, "UTF-8").toLowerCase();
        System.out.println(sign);
        if (Security.getProvider("BC") == null){
            Security.addProvider(new BouncyCastleProvider());
        }
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
        SecretKeySpec secretKeySpec = new SecretKeySpec(sign.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        return new String(cipher.doFinal(decode));
    }
    /**
     * 获取RSA加密公钥
     */
    public String getRsaPublicKey() {
        int maxRetries = 3;
        for (int retryCount = 0; retryCount < maxRetries; retryCount++) {
            try {
                System.out.println("尝试获取RSA公钥,第" + (retryCount + 1) + "次");
                // 构建请求参数
                Map<String, String> params = new HashMap<>();
                params.put("mch_id", wechatPayConfig.getMchId());
                params.put("sign_type", "MD5");
                params.put("nonce_str", generateNonceStr());
                // 生成签名
                String sign = weixinSignature(params);
                params.put("sign", sign);
                // 转换为XML
                String xmlParams = XMLUtil.mapToXml(params);
                // 打印请求参数
                System.out.println("请求参数: " + xmlParams);
                // 使用证书发送请求(关键修改:使用postWithCert而非普通HTTP请求)
                String result = postWithCert("https://fraud.mch.weixin.qq.com/risk/getpublickey", xmlParams);
                // 打印响应结果
                System.out.println("响应结果: " + result);
                // 解析结果
                Map<String, String> resultMap = XMLUtil.xmlToMap(result);
                System.out.println("获取RSA公钥结果: " + resultMap);
                // 检查返回状态
                if (!"SUCCESS".equals(resultMap.get("return_code"))) {
                    throw new Exception("RSA公钥获取失败: " + resultMap.get("return_msg"));
                }
                // 保存公钥到本地文件
                savePublicKeyToClasspath(resultMap.get("pub_key"));
                return resultMap.get("pub_key");
            } catch (Exception e) {
                System.err.println("获取RSA公钥异常: " + e.getMessage() + ", 重试次数: " + (retryCount + 1));
                e.printStackTrace();
                // 如果是最后一次重试,抛出异常
                if (retryCount == maxRetries - 1) {
                    return null;
                }
                // 重试前等待一段时间
                try {
                    Thread.sleep(1000 * (retryCount + 1)); // 指数退避
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    return null;
                }
            }
        }
        return null;
    }
    /**
     * 保存RSA公钥到文件夹
     * @param publicKey RSA公钥内容
     */
    private static void savePublicKeyToClasspath(String publicKey) throws IOException {
        // 创建 cert 目录(如果不存在)
        Path certDir = Paths.get(CERT_FOLDER);
        if (!Files.exists(certDir)) {
            Files.createDirectories(certDir); // 自动创建目录
        }
        // 写入公钥文件(UTF-8 编码)
        Path keyFile = certDir.resolve(RSA_PUBLIC_KEY_FILENAME);
        Files.write(keyFile, publicKey.getBytes(StandardCharsets.UTF_8));
    }
    /**
     * 从文件夹加载RSA公钥
     * @return RSA公钥内容
     */
    private static String loadPublicKeyFromClasspath() throws IOException {
        Path keyFile = Paths.get(CERT_FOLDER + RSA_PUBLIC_KEY_FILENAME);
        byte[] bytes = Files.readAllBytes(keyFile); // 读取所有字节
        return new String(bytes, StandardCharsets.UTF_8); // 转为UTF-8字符串
    }
    /**
     * 加载公钥 返回PublicKey对象
     */
    public static PublicKey loadPublicKey(String pemContent) throws Exception {
        // 读取PEM文件内容
//        String pemContent = new String(Files.readAllBytes(Paths.get(CERT_FOLDER + RSA_PUBLIC_KEY_FILENAME)), StandardCharsets.UTF_8);
        // 移除PEM头尾标记
        String publicKeyPEM = pemContent
                .replace("-----BEGIN RSA PUBLIC KEY-----", "")
                .replace("-----END RSA PUBLIC KEY-----", "")
                .replaceAll("\\s", ""); // 去除换行/空格
        // 解码Base64
        byte[] encoded = Base64.getDecoder().decode(publicKeyPEM);
        // 手动解析PKCS#1格式
        DerInputStream derReader = new DerInputStream(encoded);
        DerValue[] seq = derReader.getSequence(0);
        BigInteger modulus = seq[0].getBigInteger();
        BigInteger exponent = seq[1].getBigInteger();
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
        return KeyFactory.getInstance("RSA").generatePublic(keySpec);
    }
    /**
     * 使用RSA-OAEP加密数据
     * @param plaintext 待加密的明文
     * @return Base64编码的密文
     */
    public static String encrypt(String plaintext, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    /**
     * 商户付款到银行卡(优先使用本地保存的公钥)
     * @param partnerTradeNo 商户订单号
     * @param bankNo 银行卡号
     * @param trueName 银行卡真实姓名
     * @param bankCode 银行编码
     * @param amount 金额(分)
     * @param desc 付款说明
     * @return 付款结果
     */
    public Map<String, String> payToBankCard(String partnerTradeNo, String bankNo, String trueName,
                                             String bankCode, BigDecimal amount, String desc) throws Exception {
        int i = amount.multiply(new BigDecimal("100")).intValue();
        // 1. 尝试从本地加载RSA公钥
        String pubKey = loadPublicKeyFromClasspath();
        // 2. 如果本地没有公钥或公钥无效,则从微信获取新公钥
        if (pubKey == null || pubKey.isEmpty()) {
            pubKey = getRsaPublicKey();
        }
        //公钥对象
        PublicKey publicKey = loadPublicKey(pubKey);
        // 3. 使用RSA公钥加密银行卡号和真实姓名
        String encryptedBankNo = encrypt(bankNo, publicKey);
        String encryptedTrueName = encrypt(trueName, publicKey);
        // 4. 构建请求参数
        Map<String, String> params = new HashMap<>();
        params.put("mch_id", wechatPayConfig.getMchId());
        params.put("partner_trade_no", partnerTradeNo);
        params.put("enc_bank_no", encryptedBankNo);
        params.put("enc_true_name", encryptedTrueName);
        params.put("bank_code", bankCode);
        params.put("amount", String.valueOf(i));
        params.put("desc", desc);
        params.put("nonce_str", generateNonceStr());
        // 生成签名
        String sign = weixinSignature(params);
        params.put("sign", sign);
        // 将参数转换为XML
        String xmlParams = XMLUtil.mapToXml(params);
        // 5. 发送请求到微信支付付款到银行卡接口
        String url = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
        String result = postWithCert(url, xmlParams);
        // 解析返回结果
        Map<String, String> resultMap = XMLUtil.xmlToMap(result);
        // 验证签名
        if (!verifySign(resultMap, wechatPayConfig.getKey())) {
            throw new Exception("付款到银行卡签名验证失败");
        }
        return resultMap;
    }
    public static void main(String[] args) throws IOException {
        String info="CjlaS7RVnPn7zzP5ByZDxUN7OrXGp1/DEdO0qahpIqDH/gTNHb/U7VmrVV0S4lXrIa0N8FEREC3CdIeT4XB5P4D0E8TSURu6J/cD01hFu28f0JDRfeips3vSpTgznRGyCfnUBDPYwyrVeP29Wac7WAb3CCcJf7OZWaweOUkaKjaBRa1GzMZcguSZnQJz0cD5Jb4HbTMvM0VAebfCY9aXdfFBIbm+cPYESo3awqwkNTQeT4V+FViw8f8sjkH0TScMgWBiSKmQC837BLD27yIGklqlYkDP2IMeiNw+b12qCAGszfp2vYd3X+HpViXkQQet3PJWYlAm55R+IgvschP7Ub65XzLINfQrJKrQUXiKKO2LwoSRSwZvfDkR8G8E8X59CnU2XvWKeos5Y0q8ckbJb97yI+09nNgMjYyJoVCVjTFgFMDEQ4+e3CpYRhD6V/3RBp+TvBwszldbRav2XEuCXL2kCJyJEAqLPMNyfYBSNF8z1btjyz0+y/xQQcySKlQInZ710FxSE7KwRSBQ92j9nDdlR7UxCrPVCkEd+GrVNSqqnyjNh1J/rPJPHvvGwkPPq72TKiw6ZgaIgIDhy0/lWHTclo4sjYAWuUVfg3CJ8dqkuQwVZ7i0+NiahIl78RtcUph8NR48yUgBkN7WhCcu5wLbg2tu8Qe0SIwHF+RW1x9Yc8akEkNbMd4xzs8lY5MYEU9V16U8RyWJuwPDph3RnmV8HQ+2hfzmjCvPkBwtfR8P5VdK86OIsHfnfQxAcPM2a86tOBBzFXPrLHgd2CRcDKH+MXTw7RSH/bk1PiMUAWF8TQsNDzgUlznJnkjiQxoym/4ZUf4C6072KKQHbp6bgBYkBhJLT2lmjVMNSX5b1SXM9eTQixRfq6MKGw3P8XJnKdofktVv+KtSzWQlW0C8p504NWACiExupF5EII7FG+xCWt7urWUbc4NRI36UFrKToQCLVv6UBCXt/t9iWlvs6SfuZhpCexeMmZWeiIldzRu87U9rXR46Hu7DAL8dZ+0ItsIZYThSIABzZgaLKggXlkjyAcbcPYKO7egrCmDtFhzHuh4uA3VeBylL3/ZLZ4FUedn/8L4e2iAu22Qj46ORlu17W5R8Ez9kubydeAgC9PkWnjptaubPxE0bjPN69tec";
        String key="fD0JzscfMf295SYtRK3MnPRjSCA4Gahr";
        try {
            String decrypted = decrypt(info, key);
            System.out.println("解密结果: " + decrypted);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static String decrypt(String encryptedStringA, String merchantKey) throws Exception {
        // 1. 对加密串A做base64解码,得到加密串B
        byte[] decode = Base64.getDecoder().decode(encryptedStringA);
        // 2. 对商户key做md5,得到32位小写key*
        String sign = MD5AndKL.MD5Encode(merchantKey, "UTF-8").toLowerCase();
        // 3. 确保BouncyCastle提供者已添加
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
        // 4. 使用AES-256-ECB解密(PKCS7Padding)
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
        // 注意:微信要求使用AES-256,所以密钥应为32字节(256位)
        // 如果MD5结果是32字节(256位),直接使用
        byte[] aesKey = sign.getBytes(StandardCharsets.UTF_8);
        SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        // 执行解密并指定UTF-8编码
        byte[] decryptedBytes = cipher.doFinal(decode);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }
}
pt-errand/src/main/java/com/ruoyi/errand/utils/wx/XMLUtil.java
New file
@@ -0,0 +1,52 @@
package com.ruoyi.errand.utils.wx;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
 * XML工具类
 */
public class XMLUtil {
    /**
     * 将Map转换为XML字符串
     */
    public static String mapToXml(Map<String, String> params) {
        Document document = DocumentHelper.createDocument();
        // 禁用XML声明
        document.setXMLEncoding(null);  // 关键设置
        Element root = document.addElement("xml");
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue() != null ? entry.getValue() : "";
            root.addElement(key).setText(value);
        }
        return document.asXML();
    }
    /**
     * 将XML字符串转换为Map
     */
    public static Map<String, String> xmlToMap(String xmlStr) throws DocumentException {
        Map<String, String> map = new HashMap<>();
        Document document = DocumentHelper.parseText(xmlStr);
        Element root = document.getRootElement();
        for (Iterator<?> iterator = root.elementIterator(); iterator.hasNext();) {
            Element element = (Element) iterator.next();
            // 关键修改:获取元素内所有内容(包括CDATA)
            String value = element.getStringValue(); // 自动处理CDATA
            map.put(element.getName(), value);
        }
        return map;
    }
}
pt-errand/src/main/resources/cert/apiclient_cert.p12
Binary files differ
pt-errand/src/main/resources/cert/apiclient_cert.pem
New file
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEITCCAwmgAwIBAgIUPUgZIaX6EgOwzfLoTtFUMq/kxWcwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjUwNjE2MDI1MzAyWhcNMzAwNjE1MDI1MzAyWjB7MRMwEQYDVQQDDAox
NzE5ODYyOTAyMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM
HuS6keWNl+eOruWEv+enkeaKgOaciemZkOWFrOWPuDELMAkGA1UEBhMCQ04xETAP
BgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
6o6cHFkmgta28WJV9LeAKSuNIdzqtOuJRalZQEEYb4XRVek5ayeibscB0EZxZ3W+
qKPPnthXNxLRROPmoGfqE/2Nkpvkd/wRwAesr+PuhEjU2MLdhwcXrO3zGARiJUZO
EF0iEdB4/rCQHJzeFU0DGA4fCOx12VSk133HYY3otsbIBoPQzPmeGkRl1TkbXn0B
wV+478FcJtp+UdWlbnu1O8Y+wcF7P5WWtk1JTT76injNdUc4E+evqL01z12MnFzR
f7QMzMuA5WXbe5aW/LlZZn2M7VsCJeke0hwnagbq/Yh9r85dEoFsuYqv9sf75HBM
thLrfS+aYkmhcbi6B49opQIDAQABo4G5MIG2MAkGA1UdEwQCMAAwCwYDVR0PBAQD
AgP4MIGbBgNVHR8EgZMwgZAwgY2ggYqggYeGgYRodHRwOi8vZXZjYS5pdHJ1cy5j
b20uY24vcHVibGljL2l0cnVzY3JsP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3
NTQ5ODQ2QzAxQzNFOEVCRDImc2c9SEFDQzQ3MUI2NTQyMkUxMkIyN0E5RDMzQTg3
QUQxQ0RGNTkyNkUxNDAzNzEwDQYJKoZIhvcNAQELBQADggEBAJ30OsPQNRyZtEGU
z8Exw5xrP+ag3Og5r2n3CYsGldYz5e1nlAsiKBKput+lq3Bn/sbD1h0AFE+lAVOk
Jq0YdFVbjAiu85/ATdSY5YtCNKTGuEW+gLUWrR/H4SLBHjmBPTVQ6F717V+6KQz4
Xqx/licZkanRTlYlRYh+/zBnQptI/9KD6Ee6WjeyJXFNFdApXQMsdSYNkOQQ9E1B
jEUjoNNZWcCGWEsePHIPlC8r8fhZ6Lb2vVotTsxl3wEWqa+StCPd7Bz3/OtRlYxQ
gA5AMB22CAgcZLvmiQjcwBmc8X69FiXvaC4xai0QneLktoUJI8OEoRpl/Po5RDaM
nJodWMA=
-----END CERTIFICATE-----
pt-errand/src/main/resources/cert/apiclient_key.pem
New file
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDqjpwcWSaC1rbx
YlX0t4ApK40h3Oq064lFqVlAQRhvhdFV6TlrJ6JuxwHQRnFndb6oo8+e2Fc3EtFE
4+agZ+oT/Y2Sm+R3/BHAB6yv4+6ESNTYwt2HBxes7fMYBGIlRk4QXSIR0Hj+sJAc
nN4VTQMYDh8I7HXZVKTXfcdhjei2xsgGg9DM+Z4aRGXVORtefQHBX7jvwVwm2n5R
1aVue7U7xj7BwXs/lZa2TUlNPvqKeM11RzgT56+ovTXPXYycXNF/tAzMy4DlZdt7
lpb8uVlmfYztWwIl6R7SHCdqBur9iH2vzl0SgWy5iq/2x/vkcEy2Eut9L5piSaFx
uLoHj2ilAgMBAAECggEAL5Cf47fIcXvtOWIBoFCd8rtcMWPFTM7+1VuUN817kRIH
824KMMqmy+QbYAsI8DwWX8hoUAP7G7X7LgcxO5IXC9q9HN/0IsjBKLnlsP193uGO
GC7cEYfEq1LNmy84X+qz5emdARPPlYZkkwjUmGk3mWczr/GTrHDXxMNC7WuDp5yg
icBweawlSnpT0w2qjg/OdrIA25j9jpfT7DSfd0O8yxkhLvGEgY8i8/MYgpmE6MBF
qE0SOdw0olTPlyXt7nRat90A3rFrl6VnIYjL8Q3GXtQ83YW9jQtNwkfQYfeX1ZBr
HvwZHyC1agDFeqq+0meZf05uhlnPObmBNs4+JLKJ+QKBgQD5A5TZAU2W5wclZQKS
veV2tSEnv1V/qmw3upyJbf3qrvWprNhCFAywjJADLATSGhPAqrvTFuVhiwPnDqB3
yASMw+Ealsk8ZE6ZTbk1JT9PzpJoAP21OnwS10iC46NRwdGbmS9vKBKBTPxRKOi2
kvzspgMti/Jg55hKkJj4QcXrSwKBgQDxIzLiLkjYft8g+aRqRlIIl4EIH8gHpG6J
Fab9VoiTwEkzCJuk54GRxZyExxPflSneDJALvvmgoHNY7KDIdxHcP8c4aOUjFRXl
KUgba6Zt+n4pjQqazW/X+pC2LHjAswWnbQxDCGi+wna5z8FscAgVnVW0/UqGHWi9
Y5SzgAsVzwKBgQCoYvibidsK6S0W52hHDKyHilJiS2soinjlcoZ6FGv479jlpSEU
BfTSyip0Sqbz4Hhs98dNJhV00YmRDH4MobAZ9DdbQI3SDc5ssndEbeyTLhAozkrB
60uNfhDlmcON/K+eNYcy9nkVAJc61pwPIfRwno5VlWYQi2ubOI6IigmpYwKBgE1j
l4wBgL2Ckke59utooCFDxlR+JqtVOWhje5FouTJ6DsQDKjiVV/8Zpa7zWUxzSdmK
vJwYcXL8q6hJYRyVIjVGfsB64bcNqFZAlnS+as53CxB4xIOEFTYCo3jj8ukdS149
YCcPRtaaAJKHu7L6jY2qTfxlIgrC23+Uuv+Uw3n/AoGBAK3cveuP64WTfXhlHlJn
v2SJzmIG1Clvcz091+CJRC6i0UL8QjxCadzTtJu5FyRONje8LNSVeG6IdPSHXDQF
deiGbWmVLEBItOQBTlMcgEsy7kgcWG5FPOjgWjMbtJe1bSI9TtMdlkgFxfInHGYK
bJbmLc3vMs/ZsZntBX28f0pB
-----END PRIVATE KEY-----
pt-errand/src/main/resources/mapper/AddressBookMapper.xml
@@ -10,25 +10,28 @@
            recipient_name,
            recipient_phone,
            address_detail,
            is_default
            is_default,
            region_extend
        from
            t_address_book
        where
            del_flag = 0
        and community_id =#{communityId}
        and app_user_id =#{userId}
        ORDER BY tab.is_default DESC , tab.create_time DESC
        ORDER BY is_default DESC , create_time DESC
    </select>
    <select id="addressBookList" resultType="com.ruoyi.errand.object.vo.app.AddressBookListVO">
        select
            tab.id,
            tab.community_id,
            tc.communityName,
            tc.name communityName,
            tab.recipient_name,
            tab.recipient_phone,
            tab.address_detail,
            tab.is_default
            tab.is_default,
            tc.region_id,
            tab.region_extend
        from
            t_address_book  tab
        inner join
pt-errand/src/main/resources/mapper/AppUserMapper.xml
@@ -15,7 +15,8 @@
            tau.phone as phone,
            tau.vip_id AS vipId,
            tau.first_order as isFirstOrder,
            tau.end_time as endTime
            tau.end_time as endTime,
            tau.region_extend
        FROM
            t_app_user tau
                LEFT JOIN
@@ -44,7 +45,9 @@
            tau.sex,
            tau.vip_id,
            tvs.vip_name as vipName,
            tau.endTime
            tau.end_time,
            tau.birthday,
            tau.region_extend
        from
            t_app_user tau
        left join
@@ -59,7 +62,8 @@
    </select>
    <select id="countByCreateTimeBetween" resultType="java.lang.Integer">
        SELECT COUNT(*) FROM t_app_user WHERE create_time BETWEEN #{start} AND #{end}  and del_flag=0 and status !=3
        SELECT COUNT(*) FROM t_app_user WHERE create_time BETWEEN #{start} AND #{end}
--                                           and del_flag=0 and status !=3
    </select>
    <select id="countGroupByDate" resultType="java.util.Map">
@@ -90,8 +94,10 @@
    <select id="getCourierByCommunityId" resultType="java.util.Map">
        select
            tau.id as `id`,
            tc.id as courierId,
            tau.wx_openid as `openid`,
            tc.phone as `phone`
            tc.phone as `phone`,
            tc.status as status
        from
            t_community_courier tcc
        left join t_app_user tau on tcc.courier_id = tau.courier_id
@@ -125,7 +131,7 @@
            and end_time &lt;  CURRENT_TIMESTAMP or end_time is null
        </if>
        <if test="dto.status!=null  ">
            and status =#{status}
            and status =#{dto.status}
        </if>
    </select>
pt-errand/src/main/resources/mapper/CommunityMapper.xml
@@ -16,6 +16,9 @@
    <select id="getTotalCommunityList" resultType="com.ruoyi.errand.object.vo.app.CommunityListVO">
        select id ,name
        from t_community where del_flag=0
        <if test="name != null and '' != name">
            and name like concat('%',#{name},'%')
        </if>
    </select>
    <select id="getAllCommunityList" resultType="com.ruoyi.errand.object.vo.sys.AllCommunityListVO">
        select
@@ -26,10 +29,14 @@
        where
            del_flag=0
        and
        id not in
        <foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
            #{item}
        </foreach>
            status = 0
        <if test="list!=null and list.size>0">
            and id not in
            <foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
                #{item}
            </foreach>
        </if>
    </select>
    <select id="getCommunityPageList" resultType="com.ruoyi.errand.object.vo.sys.CommunityPageListVO">
        select
@@ -43,9 +50,9 @@
            from    t_community tc
        left join  t_region tr on tc.region_id = tr.id
        left join t_community_courier tcc on tc.id = tcc.community_id
        left join t_courier tco on tcc.courier_id = toc.id
        left join t_courier tco on tcc.courier_id = tco.id
        where
            del_flag=0
            tc.del_flag=0
        <if test="dto.name !=null  and ''!= dto.name">
            and tc.name like concat('%',#{dto.name},'%')
        </if>
@@ -64,5 +71,6 @@
        <if test="dto.status!=null">
            and tc.status =#{dto.status}
        </if>
        order by  tc.create_time desc
    </select>
</mapper>
pt-errand/src/main/resources/mapper/CourierMapper.xml
@@ -9,7 +9,7 @@
            tc.phone as phone,
            tc2.name as communityName
        from t_courier tc
        left join t_community_courier on tc.id = tcc.courier_id
        left join t_community_courier tcc on tc.id = tcc.courier_id
        left join t_community tc2 on tcc.community_id = tc2.id
        where
            tc.del_flag=0
@@ -23,6 +23,7 @@
                AND MONTH(receiving_time) = MONTH(CURDATE()) THEN 1 END) AS `month`
        FROM t_order
        WHERE courier_id = #{courierId}
          and del_flag = 0
          AND order_status IN (2, 4, 5) -- 进行中、已完成、已评价状态
          AND receiving_time IS NOT NULL;
    </select>
@@ -33,20 +34,35 @@
            o.recipient_name as recipientName,
            o.recipient_phone as recipientPhone,
            o.order_status as orderStatus,
            o.receiving_time as receivingTime,
            o.order_time as receivingTime,
            te.rating as rating
        from
            t_order o
        left join  t_evaluation te on o.id = te.order_id
            o.courier_id = #{courierId}  -- 替换为实际跑腿ID
            AND o.del_flag = 0          -- 过滤未删除的订单
        and o.payStatus = 2            -- 过滤未支付的订单
        left join  t_evaluation te on o.id = te.order_id and te.type = 0
        where
        o.del_flag = 0          -- 过滤未删除的订单
        and o.pay_status = 2
        and o.order_status != 3-- 过滤未支付的订单
        <choose>
            <!-- 当状态=1时,按社区ID查询 -->
            <when test="orderStatus == 1">
                AND o.community_id = #{communityId}
            </when>
            <!-- 当状态为全部时,按社区ID或者跑腿员id查询 -->
            <when test="orderStatus == null or orderStatus == 1">
                AND ((o.community_id = #{communityId} and order_status = 1) or o.courier_id = #{courierId})
            </when>
            <!-- 其他状态按快递员ID查询 -->
            <otherwise>
                AND o.courier_id = #{courierId}
            </otherwise>
        </choose>
        <if test="orderStatus !=null and orderStatus !=0">
            AND o.order_status = #{orderStatus}  -- 订单状态筛选条件
        </if>
        ORDER BY
            CASE WHEN o.order_status = 1 THEN 0 ELSE 1 END,  -- 待确认订单置顶
    o.order_time DESC;  -- 其余订单按下单时间倒序
        o.order_time DESC
    </select>
    <select id="getCourierPageList" resultType="com.ruoyi.errand.object.vo.sys.CourierPageListVO">
        select
@@ -61,7 +77,7 @@
        where
            tc.del_flag=0
        <if test="dto.name !=null and ''!=dto.name">
            AND tc.name = #{dto.name}
            AND tc.name like concat ('%',#{dto.name},'%')
        </if>
        <if test="dto.phone !=null and ''!=dto.phone">
            AND tc.phone = #{dto.phone}
@@ -75,10 +91,12 @@
            tc.name as name,
            tc.phone as phone,
            tc.id_card as idCard,
            tcc.community_id as communityId
            tcc.community_id as communityId,
            tcm.name as communityName,
            tc.create_time as createTime
            tc.status as status
            tc.create_time as createTime,
            tc.status as status,
            tc.front_view as frontView,
            tc.back_view as backView
        from t_courier tc
                 left join t_community_courier tcc on tc.id = tcc.courier_id
                 left join t_community tcm on tcc.community_id = tcm.id
@@ -92,12 +110,16 @@
        from
            t_courier
        where
            del_flag=0
        and
            del_flag = 0
          and status = 1
        <if test="couriers!=null and couriers.size>0">
            and
            id not in
        <foreach collection="couriers" item="item" index="index" open="(" close=")" separator=",">
            #{item}
        </foreach>
            <foreach collection="couriers" item="item" index="index" open="(" close=")" separator=",">
                #{item}
            </foreach>
        </if>
    </select>
</mapper>
pt-errand/src/main/resources/mapper/EvaluationMapper.xml
@@ -11,6 +11,7 @@
        where
            o.courier_id=#{courierId}
        and o.del_flag=0
        and te.type = 0
        and te.rating=5.0
    </select>
</mapper>
pt-errand/src/main/resources/mapper/FeedbackMapper.xml
@@ -16,8 +16,9 @@
        <if test="dto.phone != null and dto.phone !='' ">
            and phone like concat('%',#{dto.phone},'%')
        </if>
        <if test="dto.status != null  ">
        <if test="dto.status != null and dto.status != -1 ">
            and status= #{dto.status}
        </if>
        order by create_time desc
    </select>
</mapper>
pt-errand/src/main/resources/mapper/OrderMapper.xml
@@ -11,19 +11,22 @@
            o.recipient_phone,
            o.order_status,
            o.order_time,
            o.rating,
            e.rating,
            o.courier_id,
            c.name,
            c.phone
            c.name courierName,
            c.phone courierPhone
            from t_order o
            left join t_courier c on o.courier_id = c.id
            left join t_courier c on c.id = o.courier_id
            left join t_evaluation e on o.id = e.order_id and e.type =0
            where
                o.del_flag=0
              and o.order_status != 3
              and o.pay_status=2
              and o.app_user_id = #{appUserId}
              <if test="orderStatus!=null and orderStatus!=0">
                  and o.order_status = #{orderStatus}
              </if>
        order by o.order_time desc
    </select>
    <select id="getOrderDetail" resultType="com.ruoyi.errand.object.vo.app.OrderDetailVO">
        select
@@ -43,17 +46,20 @@
            o.order_time as orderTime,
            o.pay_method as payMethod,
            o.payment_amount as paymentAmount,
            c.courier_name as courierName,
            c.courier_phone as courierPhone,
            c.name as courierName,
            c.phone as courierPhone,
            e.id as evaluationId,
            e.rating as rating,
            e.content as content
            e.content as content,
            e2.rating as courierRating,
            e2.content as courierContent
            from t_order o
        left join t_courier c on o.courier_id = c.id
        left join t_evaluation e on o.id = e.order_id
        left join t_evaluation e on o.id = e.order_id and e.type = 0
        left join t_evaluation e2 on o.id = e2.order_id and e2.type = 1
        where
            o.id=#{id}
            and o.del_flag=0
            and e.type = 0
    </select>
    <select id="getOrderTopInfoByDate" resultType="java.util.Map">
@@ -64,10 +70,11 @@
            t_order
        where
            del_flag=0
          and pay_status = 2
        and
            order_status in (4,5)
        <if test="communityId!=null and communityId!=0">
            and communityId =#{communityId}
            and community_id =#{communityId}
        </if>
        <if test="start!=null and end!=null">
            and order_time BETWEEN #{start} AND #{end}
@@ -89,7 +96,10 @@
            COALESCE(SUM(payment_amount), 0.00) AS amount
        FROM t_order
        WHERE order_time BETWEEN #{start} AND #{end}
          and del_flag=0 and order_status in (4,5)
          and del_flag=0 and order_status in (4,5)and pay_status = 2
        <if test="communityId!=null and 0!= communityId">
            and community_id =#{communityId}
        </if>
        GROUP BY
            CASE #{datePattern}
                WHEN 'HH时' THEN DATE_FORMAT(order_time, '%H时')
@@ -140,15 +150,12 @@
                and tau.phone like concat('%',#{dto.phone},'%')
            </if>
        <if test="dto.orderStatus!=null and 0!=dto.orderStatus and dto.orderStatus !=4">
        <if test="dto.orderStatus!=null and 0!=dto.orderStatus ">
            and t.order_status = #{dto.orderStatus}
        </if>
        <if test="dto.orderStatus ==4">
            and t.order_status in(4,5)
        <if test="dto.startTime!=null and dto.endTime != null">
            and t.order_time between #{dto.startTime} and #{dto.endTime}
        </if>
            <if test="dto.startTime!=null and dto.endTime != null">
                and t.order_time between #{dto.startTime} and #{dto.endTime}
            </if>
        ) t
        where
            1=1
@@ -161,8 +168,10 @@
    <select id="financeStatistics" resultType="com.ruoyi.errand.object.vo.sys.FinanceStatisticsVO">
        select * from (
                SELECT t.id as id,
                       t.order_amount as money,
                       t.order_time as orderTime,
                       1 as type,
                        t.pay_method as payMethod,
                       t.order_number as orderNumber,
                       tau.name as appUserName,
                       tau.phone as phone,
@@ -180,41 +189,45 @@
                <if test="dto.orderStatus!=null and 0!=dto.orderStatus and dto.orderStatus !=4">
                    and t.order_status = #{dto.orderStatus}
                </if>
        <if test="dto.orderStatus ==4">
            and t.order_status in(4,5)
        </if>
                <if test="dto.startTime!=null and dto.endTime != null">
                    and t.order_time between #{dto.startTime} and #{dto.endTime}
                </if>
            UNION ALL
                SELECT t.id as id,
                t.order_time as orderTime,
                2 as type,
                t.order_number as orderNumber,
                tau.name as appUserName,
                tau.phone as phone,
                t.order_status as orderStatus
                FROM t_vip_order t
                INNER JOIN t_app_user tau ON t.app_user_id = tau.id
                WHERE t.del_flag=0
        and t.pay_status=2
                <if test="dto.appUserName!=null and  ''!=dto.appUserName">
                    and tau.name like concat('%',#{dto.appUserName},'%')
                </if>
                <if test="dto.phone!=null and  ''!=dto.phone">
                    and tau.phone like concat('%',#{dto.phone},'%')
                </if>
                <if test="dto.orderStatus!=null and 0!=dto.orderStatus and dto.orderStatus !=4">
                    and t.order_status = #{dto.orderStatus}
                </if>
                <if test="dto.orderStatus ==4">
                    and t.order_status in(4,5)
                </if>
                <if test="dto.startTime!=null and dto.endTime != null">
                    and t.order_time between #{dto.startTime} and #{dto.endTime}
                </if>
                <if test="dto.payMethod!=null">
                    and t.pay_method = #{dto.payMethod}
                </if>
                <if test="dto.payMethod==null || dto.payMethod==0">
                UNION ALL
                    SELECT t.id as id,
                       t.order_amount as money,
                        t.order_time as orderTime,
                        2 as type,
                        0 as payMethod,
                        t.order_number as orderNumber,
                        tau.name as appUserName,
                        tau.phone as phone,
                        t.order_status as orderStatus
                    FROM t_vip_order t
                    INNER JOIN t_app_user tau ON t.app_user_id = tau.id
                    WHERE t.del_flag=0
                        and t.pay_status=2
                    <if test="dto.appUserName!=null and  ''!=dto.appUserName">
                            and tau.name like concat('%',#{dto.appUserName},'%')
                    </if>
                    <if test="dto.phone!=null and  ''!=dto.phone">
                            and tau.phone like concat('%',#{dto.phone},'%')
                    </if>
                    <if test="dto.orderStatus!=null and 0!=dto.orderStatus ">
                            and t.order_status = #{dto.orderStatus}
                    </if>
                    <if test="dto.startTime!=null and dto.endTime != null">
                        and t.order_time between #{dto.startTime} and #{dto.endTime}
                    </if>
                </if>
                ) t
            where
@@ -266,14 +279,13 @@
            and o.order_time between #{dto.orderStartTime} and #{dto.orderEndTime}
        </if>
        <if test="dto.finishStartTime!=null and dto.finishEndTime != null">
            and o.finishTime between #{dto.finishStartTime} and #{dto.finishEndTime}
            and o.finish_time between #{dto.finishStartTime} and #{dto.finishEndTime}
        </if>
        <if test="dto.orderStatus!=null and 0!=dto.orderStatus and dto.orderStatus !=4">
        <if test="dto.orderStatus!=null and 0!=dto.orderStatus">
            and o.order_status = #{dto.orderStatus}
        </if>
        <if test="dto.orderStatus ==4">
            and o.order_status in(4,5)
        </if>
        order by o.order_time desc
    </select>
    <select id="detail" resultType="com.ruoyi.errand.object.vo.sys.OrderSysDetailVO">
        select
@@ -303,7 +315,7 @@
        inner join t_app_user tau on o.app_user_id = tau.id
        left join t_courier tc on o.courier_id = tc.id
        left join t_evaluation teu on o.id = teu.order_id and teu.type=0
        left join t_evaluation tec on o.id = teu.order_id and teu.type=1
        left join t_evaluation tec on o.id = tec.order_id and tec.type=1
        where
            o.id=#{id}
    </select>
@@ -311,7 +323,9 @@
        select * from (
        SELECT t.id as id,
        t.order_time as orderTime,
        t.order_amount as money,
        1 as type,
        t.pay_method as payMethod,
        t.order_number as orderNumber,
        tau.name as appUserName,
        tau.phone as phone,
@@ -335,10 +349,17 @@
        <if test="dto.startTime!=null and dto.endTime != null">
            and t.order_time between #{dto.startTime} and #{dto.endTime}
        </if>
        <if test="dto.payMethod!=null">
            and t.pay_method = #{dto.payMethod}
        </if>
        <if test="dto.payMethod==null || dto.payMethod==0">
        UNION ALL
        SELECT t.id as id,
        t.order_time as orderTime,
        t.order_amount as money,
        2 as type,
        0 as payMethod,
        t.order_number as orderNumber,
        tau.name as appUserName,
        tau.phone as phone,
@@ -355,15 +376,14 @@
            and tau.phone like concat('%',#{dto.phone},'%')
        </if>
        <if test="dto.orderStatus!=null and 0!=dto.orderStatus and dto.orderStatus !=4">
        <if test="dto.orderStatus!=null and 0!=dto.orderStatus ">
            and t.order_status = #{dto.orderStatus}
        </if>
        <if test="dto.orderStatus ==4">
            and t.order_status in(4,5)
        </if>
        <if test="dto.startTime!=null and dto.endTime != null">
            and t.order_time between #{dto.startTime} and #{dto.endTime}
        </if>
        </if>
        ) t
        where
@@ -414,7 +434,7 @@
            and o.order_time between #{dto.orderStartTime} and #{dto.orderEndTime}
        </if>
        <if test="dto.finishStartTime!=null and dto.finishEndTime != null">
            and o.finishTime between #{dto.finishStartTime} and #{dto.finishEndTime}
            and o.finish_time between #{dto.finishStartTime} and #{dto.finishEndTime}
        </if>
        <if test="dto.orderStatus!=null and 0!=dto.orderStatus and dto.orderStatus !=4">
            and o.order_status = #{dto.orderStatus}
@@ -422,5 +442,6 @@
        <if test="dto.orderStatus ==4">
            and o.order_status in(4,5)
        </if>
        order by o.order_time desc
    </select>
</mapper>
pt-errand/src/main/resources/mapper/ReportMapper.xml
@@ -9,13 +9,12 @@
            tr.community_name as communityName,
            tre.name as regionName,
            tr.address_detail as addressDetail,
            tau.name as appUserName,
            tau.phone as appUserPhone,
            tr.username as appUserName,
            tr.phone as appUserPhone,
            tr.create_time as createTime,
            tr.status as status
            from
                t_report tr
        left join t_app_user tau on tr.app_user_id = tau.id
        left join t_region tre on tr.region_id = tre.id
        where
            tr.del_flag=0
@@ -26,14 +25,14 @@
            and tre.id =#{dto.regionId}
        </if>
        <if test="dto.appUserName!=null and ''!=dto.appUserName">
            and tau.name like concat('%',#{dto.appUserName},'%')
            and tr.username like concat('%',#{dto.appUserName},'%')
        </if>
        <if test="dto.appUserPhone!=null and ''!=dto.appUserPhone">
            and tau.phone like concat('%',#{dto.appUserPhone},'%')
            and tr.phone like concat('%',#{dto.appUserPhone},'%')
        </if>
        <if test="dto.status!=null">
            and tr.status =#{dto.status}
        </if>
    order by tr.create_time desc
    </select>
</mapper>
pt-errand/src/main/resources/mapper/VipOrderMapper.xml
@@ -8,4 +8,19 @@
        from t_vip_order tvo
        left join
    </select>
    <select id="detail" resultType="com.ruoyi.errand.object.vo.sys.OrderSysDetailVO">
        select
            tvo.order_status,
            tau.name appUserName,
            tau.phone appUserPhone,
            tvo.order_number,
            tvo.order_time,
            tvo.order_amount paymentAmount
        from
                t_vip_order tvo
        left join
                t_app_user tau on tvo.app_user_id = tau.id
        where
            tvo.id =#{id}
    </select>
</mapper>
pt-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -119,7 +119,7 @@
            .authorizeHttpRequests((requests) -> {
                permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
                // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                requests.antMatchers("/login", "/register", "/captchaImage","/screen/data").permitAll()
                requests.antMatchers("/login", "/register", "/captchaImage","/screen/data","/common/upload","/system/user/profile/updatePwd").permitAll()
                    // 静态资源,可匿名访问
                    .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                    .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**","/swagger-ui/").permitAll()
pt-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
@@ -128,4 +128,8 @@
    List<MenuTreeVO> getAllRootMenu();
    List<MenuTreeVO> selectMenusByParentId(@Param("menuId") Long menuId);
    List<SysMenu> selectMenusByUserId(@Param("userId")Long userId);
    List<String> getPathsByMenuIds(@Param("ids")List<Long> ids);
}
pt-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -41,7 +41,7 @@
    public List<SysUser> selectUnallocatedList(SysUser user);
    /**
     * 通过用户名查询用户
     * 通过手机号询用户
     * 
     * @param userName 用户名
     * @return 用户对象信息
@@ -84,7 +84,7 @@
    /**
     * 重置用户密码
     * 
     * @param userName 用户名
     * @param userName 手机号
     * @param password 密码
     * @return 结果
     */
@@ -132,7 +132,9 @@
    IPage<SysUserPageListVO> getSysUserPageList(@Param("page") IPage<SysUserPageListVO> page, @Param("nickName") String nickName,@Param("phone")  Integer phone, @Param("status") String status);
    R<SysUserVO> getSysUserVO(@Param("userId") Long userId);
    SysUserVO getSysUserVO(@Param("userId") Long userId);
    SysUser selectuserByPhone(@Param("phonenumber") String phonenumber);
    List<SysUser> selectUserByDeptId(@Param("deptId")Long deptId);
}
pt-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
@@ -65,4 +65,6 @@
    void insert(@Param("userId")Long userId, @Param("roleId")Long roleId);
    SysRole selectRoleByUserId(@Param("userId")Long userId);
    List<SysUserRole> selectUserIdByRoleId(@Param("roleId")Long roleId);
}
pt-system/src/main/java/com/ruoyi/system/object/dto/AddDeptDTO.java
New file
@@ -0,0 +1,8 @@
package com.ruoyi.system.object.dto;
import lombok.Data;
@Data
public class AddDeptDTO {
    private String name;
}
pt-system/src/main/java/com/ruoyi/system/object/dto/EditSysRoleDTO.java
@@ -6,10 +6,13 @@
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
@Getter
@Setter
@ApiModel("编辑角色DTO")
public class EditSysRoleDTO extends AddSysRoleDTO {
    @ApiModelProperty("角色id")
    @NotNull(message = "角色id不能为空")
    private Long roleId;
}
pt-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
@@ -7,6 +7,7 @@
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.object.vo.SysDeptPageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -38,6 +39,8 @@
    @Autowired
    private SysRoleMapper roleMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    /**
     * 查询部门管理数据
@@ -294,6 +297,15 @@
    @Override
    public int deleteDeptById(Long deptId)
    {
        SysDept dept = deptMapper.selectDeptById(deptId);
        if (dept == null ){
            throw new ServiceException("该部门不存在");
        }
        //判断是否有用户关联部门
        List<SysUser> sysUsers = sysUserMapper.selectUserByDeptId(deptId);
        if (sysUsers.size() > 0){
            throw new ServiceException("有用户绑定该部门,不能删除");
        }
        return deptMapper.deleteDeptById(deptId);
    }
pt-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.object.dto.AddSysRoleDTO;
import com.ruoyi.system.object.dto.EditSysRoleDTO;
import com.ruoyi.system.object.vo.SysRolePageVO;
@@ -25,10 +26,6 @@
import com.ruoyi.system.domain.SysRoleDept;
import com.ruoyi.system.domain.SysRoleMenu;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.SysRoleDeptMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysRoleMenuMapper;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysRoleService;
/**
@@ -50,6 +47,10 @@
    @Autowired
    private SysRoleDeptMapper roleDeptMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    /**
     * 根据条件分页查询角色数据
@@ -350,6 +351,12 @@
    @Transactional
    public int deleteRoleById(Long roleId)
    {
        //查看角色是否有用户绑定
        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectUserIdByRoleId(roleId);
        if (!sysUserRoles.isEmpty()){
            throw new ServiceException("有用户绑定该角色,不能删除");
        }
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
        // 删除角色与部门关联
@@ -451,6 +458,8 @@
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        sysRole.setCreateBy(loginUser.getUsername());
        sysRole.setCreateTime(DateUtils.getNowDate());
        sysRole.setRoleSort(1);
        sysRole.setDelFlag("0");
        roleMapper.insertRole(sysRole);
        //添加角色菜单
        roleMenuMapper.insert(sysRole.getRoleId(),dto.getMenuIds());
@@ -468,12 +477,22 @@
        sysRole.setRoleName(dto.getRoleName());
        List<SysRole> sysRoles = roleMapper.selectRoleList(sysRole);
        if (sysRoles!=null && !sysRoles.isEmpty()){
            throw new ServiceException("该角色名称重复");
            sysRoles.forEach(role -> {
                if (!Objects.equals(role.getRoleId(), dto.getRoleId())){
                    //id不同
                    if (role.getRoleName().equals(dto.getRoleName())){
                        throw new ServiceException("该角色名称重复");
                    }
                }
            });
        }
        //删除之前的
        roleMenuMapper.deleteRoleMenuByRoleId(dto.getRoleId());
        //添加角色菜单
        roleMenuMapper.insert(sysRole.getRoleId(),dto.getMenuIds());
        roleMenuMapper.insert(dto.getRoleId(),dto.getMenuIds());
        //修改角色
        sysRole1.setRoleName(dto.getRoleName());
        roleMapper.updateRole(sysRole1);
    }
    @Override
pt-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -578,7 +578,7 @@
    @Override
    public R<SysUserVO> getInfo(Long userId) {
        return userMapper.getSysUserVO(userId);
        return R.ok(userMapper.getSysUserVO(userId));
    }
    @Override
@@ -604,7 +604,7 @@
        sysUser.setPhonenumber(dto.getPhonenumber());
        sysUser.setNickName(dto.getNickName());
        //后六位为默认密码
        sysUser.setPassword(SecurityUtils.encryptPassword(Md5Utils.hash(dto.getPhonenumber().substring(6,12))));
        sysUser.setPassword(SecurityUtils.encryptPassword(Md5Utils.hash(dto.getPhonenumber().substring(5,11))));
        sysUser.setStatus("0");
        sysUser.setDeptId(dto.getDeptId());  //添加用户-部门关系
        userMapper.insertUser(sysUser);
@@ -665,7 +665,7 @@
        if (sysUser==null){
            throw new ServiceException("该用户不存在");
        }
        sysUser.setPassword(SecurityUtils.encryptPassword(Md5Utils.hash(sysUser.getPassword().substring(6,12))));
        sysUser.setPassword(SecurityUtils.encryptPassword(Md5Utils.hash(sysUser.getPhonenumber().substring(5,11))));
        userMapper.updateUser(sysUser);
    }
@@ -673,9 +673,10 @@
    public void changeStatus(Long userId) {
        //检查用户是否存在
        SysUser sysUser = userMapper.selectUserById(userId);
        if (sysUser==null){
        if (sysUser==null || sysUser.getDelFlag().equals("2")){
            throw new ServiceException("该用户不存在");
        }
        sysUser.setStatus(Objects.equals(sysUser.getStatus(), "1") ?"0":"1");
        userMapper.updateUser(sysUser);
    }
pt-system/src/main/resources/mapper/system/SysMenuMapper.xml
@@ -144,6 +144,21 @@
        select menu_id,menu_name,path,menu_type from sys_menu
        where parent_id = #{menuId} order by order_num     asc
    </select>
    <select id="selectMenusByUserId" resultType="com.ruoyi.common.core.domain.entity.SysMenu">
        select
            m.menu_id, m.parent_id
        from  sys_user_role ur
                  left join sys_role_menu rm on ur.role_id = rm.role_id
                  left join sys_menu m on rm.menu_id =  m.menu_id
        where
            ur.user_id=#{userId}
    </select>
    <select id="getPathsByMenuIds" resultType="java.lang.String">
        select path from sys_menu where menu_id in
        <foreach collection='ids' item='id' open='(' separator=',' close=')'>
            #{id}
        </foreach>
    </select>
    <update id="updateMenu" parameterType="SysMenu">
        update sys_menu
pt-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -122,12 +122,12 @@
    
    <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
        <include refid="selectUserVo"/>
        where u.user_name = #{userName} and u.del_flag = '0'
        where u.phonenumber = #{userName} and u.del_flag = '0'
    </select>
    
    <select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
        <include refid="selectUserVo"/>
        where u.user_id = #{userId}
        where u.user_id = #{userId} and u.del_flag = '0'
    </select>
    
    <select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
@@ -189,8 +189,11 @@
    <select id="selectuserByPhone" resultType="com.ruoyi.common.core.domain.entity.SysUser">
        select * from sys_user where del_flag='0' and phonenumber =#{phonenumber}
    </select>
    <select id="selectUserByDeptId" resultType="com.ruoyi.common.core.domain.entity.SysUser">
        select * from sys_user where del_flag='0' and dept_id = #{deptId}
    </select>
    <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
    <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
         insert into sys_user(
             <if test="userId != null and userId != 0">user_id,</if>
             <if test="deptId != null and deptId != 0">dept_id,</if>
@@ -251,7 +254,7 @@
    </update>
    
    <update id="resetUserPwd" parameterType="SysUser">
         update sys_user set password = #{password} where user_name = #{userName}
         update sys_user set password = #{password} where phonenumber = #{userName}
    </update>
    
    <delete id="deleteUserById" parameterType="Long">
pt-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
@@ -19,6 +19,9 @@
    <select id="selectRoleByUserId" resultType="com.ruoyi.common.core.domain.entity.SysRole">
        select * from sys_user_role where user_id=#{userId}
    </select>
    <select id="selectUserIdByRoleId" resultType="com.ruoyi.system.domain.SysUserRole">
        select * from sys_user_role where role_id=#{roleId}
    </select>
    <delete id="deleteUserRole" parameterType="Long">
         delete from sys_user_role where user_id in