puzhibing
2023-07-04 75b60332f174363cfe67f61dea87832be708ac15
更新部分接口
36个文件已修改
48个文件已添加
4712 ■■■■■ 已修改文件
cloud-server-account/pom.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/AccountApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/controller/ClassDetailsController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/controller/StudentController.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/entity/TAppUser.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/entity/VipPayment.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/QueryStoreList.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/feignclient/other/StoreClient.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/feignclient/other/model/Store.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/mapper/TAppUserMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/mapper/VipPaymentMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/model/JoinPlayPaiVo.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/service/IVipPaymentService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/service/TAppUserService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/service/impl/VipPaymentServiceImpl.java 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/GDMapGeocodingUtil.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/GeodesyUtil.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/MD5AndKL.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java 803 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/ResultUtil.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/TaskUtil.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/TokenUtil.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/httpClinet/HttpClientUtil.java 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/util/weChat/WeChatUtil.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/resources/mapper/TAppUserMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/resources/mapper/VipPaymentMapper.tld 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/controller/CouponController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/entity/Coupon.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/AppUserClient.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/StudentClient.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/model/AppUser.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/model/Student.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/mapper/CouponMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/model/CouponListVo.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/service/ICouponService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/service/impl/CouponServiceImpl.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/util/ResultUtil.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/util/TokenUtil.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/resources/mapper/CouponMapper.tld 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-competition/src/main/java/com/dsh/competition/util/ResultUtil.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-competition/src/main/java/com/dsh/competition/util/TokenUtil.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/pom.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/entity/CoursePackagePaymentConfig.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/feignclient/account/model/AppUser.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/feignclient/other/StoreClient.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/feignclient/other/model/Store.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/mapper/CoursePackagePaymentConfigMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/mapper/TCoursePackageMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/mapper/TCoursePackagePaymentMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/model/BaseVo.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageList.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageListVo.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/service/ICoursePackagePaymentConfigService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackagePaymentService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackageService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/service/impl/CoursePackagePaymentConfigServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackagePaymentServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/service/impl/TCourseServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/util/GDMapGeocodingUtil.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/util/GeodesyUtil.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/util/ResultUtil.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/util/TokenUtil.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/util/httpClinet/HttpClientUtil.java 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/util/httpClinet/HttpResult.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/resources/mapper/CoursePackagePaymentConfigMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/resources/mapper/TCourseMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/resources/mapper/TCoursePackagePaymentMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/pom.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/controller/StoreConfigController.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/controller/StoreController.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/model/BaseVo.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/model/StoreConfigVo.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/service/StoreService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/service/impl/StoreServiceImpl.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/util/GDMapGeocodingUtil.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/util/ResultUtil.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/util/TokenUtil.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/util/httpClinet/HttpClientUtil.java 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/util/httpClinet/HttpResult.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/pom.xml
@@ -91,6 +91,11 @@
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.8.10.ALL</version>
@@ -112,6 +117,11 @@
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.gavaghan</groupId>
            <artifactId>geodesy</artifactId>
            <version>1.1.3</version>
        </dependency>
    </dependencies>
    <build>
cloud-server-account/src/main/java/com/dsh/AccountApplication.java
@@ -11,6 +11,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableScheduling;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import javax.annotation.PostConstruct;
@@ -22,6 +23,7 @@
@EnableSwagger2
@EnableFeignClients
@MBCloudApplication
@EnableScheduling//开启定时任务
@Import({WebConfig.class})
@MapperScan("com.dsh.account.mapper")
public class AccountApplication {
cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java
@@ -1,15 +1,26 @@
package com.dsh.account.controller;
import com.dsh.account.entity.TAppUser;
import com.dsh.account.model.AddAppUserVo;
import com.dsh.account.model.JoinPlayPaiVo;
import com.dsh.account.model.LoginSMSCodeVo;
import com.dsh.account.model.LoginWeChatVo;
import com.dsh.account.service.IVipPaymentService;
import com.dsh.account.service.TAppUserService;
import com.dsh.account.util.PayMoneyUtil;
import com.dsh.account.util.ResultUtil;
import com.dsh.account.util.TokenUtil;
import com.dsh.account.util.ToolUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Map;
/**
 * @author zhibing.pu
@@ -22,6 +33,15 @@
    @Autowired
    private TAppUserService appUserService;
    @Autowired
    private PayMoneyUtil payMoneyUtil;
    @Autowired
    private IVipPaymentService vipPaymentService;
    @Autowired
    private TokenUtil tokenUtil;
@@ -33,6 +53,12 @@
            @ApiImplicitParam(value = "电话号码", name = "phone", dataType = "string", required = true)
    })
    public ResultUtil getSMSCode(@RequestBody Integer type, @RequestBody String phone){
        if(ToolUtil.isEmpty(phone)){
            return ResultUtil.paranErr("phone");
        }
        if(ToolUtil.isEmpty(type)){
            return ResultUtil.paranErr("type");
        }
        try {
            ResultUtil smsCode = appUserService.getSMSCode(type, phone);
            return smsCode;
@@ -66,6 +92,12 @@
            @ApiImplicitParam(value = "登录密码", name = "password", dataType = "string", required = true)
    })
    public ResultUtil<String> loginPassword(@RequestBody String phone, @RequestBody String password){
        if(ToolUtil.isEmpty(phone)){
            return ResultUtil.paranErr("phone");
        }
        if(ToolUtil.isEmpty(password)){
            return ResultUtil.paranErr("password");
        }
        try {
            return appUserService.loginPassword(phone, password);
        }catch (Exception e){
@@ -116,6 +148,15 @@
            @ApiImplicitParam(value = "新密码", name = "password", dataType = "string", required = true)
    })
    public ResultUtil updatePassword(@RequestBody String phone, @RequestBody String code, @RequestBody String password){
        if(ToolUtil.isEmpty(phone)){
            return ResultUtil.paranErr("phone");
        }
        if(ToolUtil.isEmpty(code)){
            return ResultUtil.paranErr("code");
        }
        if(ToolUtil.isEmpty(password)){
            return ResultUtil.paranErr("password");
        }
        try {
            return appUserService.updatePassword(phone, code, password);
        }catch (Exception e){
@@ -134,6 +175,15 @@
            @ApiImplicitParam(value = "新密码", name = "password", dataType = "string", required = true)
    })
    public ResultUtil forgetPassword(@RequestBody String phone, @RequestBody String code, @RequestBody String password){
        if(ToolUtil.isEmpty(phone)){
            return ResultUtil.paranErr("phone");
        }
        if(ToolUtil.isEmpty(code)){
            return ResultUtil.paranErr("code");
        }
        if(ToolUtil.isEmpty(password)){
            return ResultUtil.paranErr("password");
        }
        try {
            return appUserService.updatePassword(phone, code, password);
        }catch (Exception e){
@@ -144,5 +194,135 @@
    @ResponseBody
    @PostMapping("/api/appUser/queryJoinPlayPai")
    @ApiOperation(value = "获取加入玩湃首页数据", tags = {"APP-加入玩湃"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "经度", name = "lon", dataType = "string", required = true),
            @ApiImplicitParam(value = "纬度", name = "lat", dataType = "string", required = true),
            @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil<JoinPlayPaiVo> queryJoinPlayPai(@RequestBody String lon, @RequestBody String lat){
        if(ToolUtil.isEmpty(lon)){
            return ResultUtil.paranErr("lon");
        }
        if(ToolUtil.isEmpty(lat)){
            return ResultUtil.paranErr("lat");
        }
        try {
            Integer uid = tokenUtil.getUserIdFormRedis();
            if(null == uid){
                return ResultUtil.tokenErr();
            }
            JoinPlayPaiVo joinPlayPaiVo = appUserService.queryJoinPlayPai(uid, lon, lat);
            return ResultUtil.success(joinPlayPaiVo);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    @ResponseBody
    @PostMapping("/api/appUser/addVipPayment")
    @ApiOperation(value = "购买年度会员", tags = {"APP-成为会员"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "支付方式(1=微信,2=支付宝)", name = "payType", dataType = "int", required = true),
            @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil addVipPayment(@RequestBody Integer payType){
        if(ToolUtil.isEmpty(payType)){
            return ResultUtil.paranErr("payType");
        }
        try {
            Integer uid = tokenUtil.getUserIdFormRedis();
            if(null == uid){
                return ResultUtil.tokenErr();
            }
            return vipPaymentService.addVipPayment(uid, payType);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 购买年度会员支付微信回调
     * @param request
     * @param response
     */
    @ResponseBody
    @PostMapping("/base/appUser/addVipPaymentWeChatCallback")
    public void addVipPaymentWeChatCallback(HttpServletRequest request, HttpServletResponse response){
        try {
            Map<String, String> map = payMoneyUtil.weixinpayCallback(request);
            if(null != map){
                String out_trade_no = map.get("out_trade_no");
                String transaction_id = map.get("transaction_id");
                String result = map.get("result");
                ResultUtil resultUtil = vipPaymentService.addVipPaymentCallback(out_trade_no, transaction_id);
                if(resultUtil.getCode() == 200){
                    PrintWriter out = response.getWriter();
                    out.write(result);
                    out.flush();
                    out.close();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 购买年度会员支付支付宝回调
     * @param request
     * @param response
     */
    @ResponseBody
    @PostMapping("/base/appUser/addVipPaymentAliCallback")
    public void addVipPaymentAliCallback(HttpServletRequest request, HttpServletResponse response){
        try {
            Map<String, String> map = payMoneyUtil.alipayCallback(request);
            if(null != map){
                String out_trade_no = map.get("out_trade_no");
                String trade_no = map.get("trade_no");
                ResultUtil resultUtil = vipPaymentService.addVipPaymentCallback(out_trade_no, trade_no);
                if(resultUtil.getCode() == 200){
                    PrintWriter out = response.getWriter();
                    out.write("success");
                    out.flush();
                    out.close();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 根据用户id获取用户信息
     * @param appUserId
     * @return
     */
    @ResponseBody
    @PostMapping("/base/appUser/queryAppUser")
    public TAppUser queryAppUser(@RequestBody Integer appUserId){
        try {
            TAppUser appUser = appUserService.getById(appUserId);
            return appUser;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}
cloud-server-account/src/main/java/com/dsh/account/controller/ClassDetailsController.java
@@ -58,9 +58,9 @@
            @ApiImplicitParam(value = "纬度值", name = "latitude", required = true, dataType = "String"),
            @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil queryCouponRecord(String longitude,String latitude,HttpServletRequest request){
    public ResultUtil queryCouponRecord(String longitude,String latitude){
        try {
            Integer userIdFormRedis = tokenUtil.getUserIdFormRedis(request);
            Integer userIdFormRedis = tokenUtil.getUserIdFormRedis();
            if(null == userIdFormRedis){
                return ResultUtil.tokenErr();
            }
@@ -102,9 +102,9 @@
            @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    @Transactional
    public ResultUtil addStu(@RequestBody StuDetailsReq stu,HttpServletRequest request){
    public ResultUtil addStu(@RequestBody StuDetailsReq stu){
        try {
            Integer userIdFormRedis = tokenUtil.getUserIdFormRedis(request);
            Integer userIdFormRedis = tokenUtil.getUserIdFormRedis();
            if(null == userIdFormRedis){
                return ResultUtil.tokenErr();
            }
@@ -124,9 +124,9 @@
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "Bearer +token", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil queryStuList(HttpServletRequest request){
    public ResultUtil queryStuList(){
        try {
            Integer userIdFormRedis = tokenUtil.getUserIdFormRedis(request);
            Integer userIdFormRedis = tokenUtil.getUserIdFormRedis();
            if(null == userIdFormRedis){
                return ResultUtil.tokenErr();
            }
cloud-server-account/src/main/java/com/dsh/account/controller/StudentController.java
New file
@@ -0,0 +1,40 @@
package com.dsh.account.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dsh.account.entity.TStudent;
import com.dsh.account.service.TStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 14:59
 */
@RestController
@RequestMapping("")
public class StudentController {
    @Autowired
    private TStudentService studentService;
    /**
     * 获取用户学员列表
     * @param appUserId
     * @return
     */
    @ResponseBody
    @PostMapping("/student/queryStudentList")
    public List<TStudent> queryStudentList(@RequestBody Integer appUserId){
        try {
            List<TStudent> list = studentService.list(new QueryWrapper<TStudent>().eq("appUserId", appUserId).eq("state", 1));
            return list;
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }
}
cloud-server-account/src/main/java/com/dsh/account/entity/TAppUser.java
@@ -127,6 +127,10 @@
     * 用户头像
     */
    private String headImg;
    /**
     * 添加时间
     */
    private Date insertTime;
}
cloud-server-account/src/main/java/com/dsh/account/entity/VipPayment.java
New file
@@ -0,0 +1,76 @@
package com.dsh.account.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.dsh.account.util.UUIDUtil;
import lombok.Data;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * @author zhibing.pu
 * @date 2023/6/24 9:58
 */
@Data
@TableName("t_vip_payment")
public class VipPayment {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 流水号
     */
    @TableField("code")
    private String code;
    /**
     * 用户id
     */
    @TableField("appUserId")
    private Integer appUserId;
    /**
     * 支付金额
     */
    @TableField("amount")
    private Double amount;
    /**
     * 支付方式(1=微信,2=支付宝)
     */
    @TableField("payType")
    private Integer payType;
    /**
     * 支付状态(1=待支付,2=已支付)
     */
    @TableField("payStatus")
    private Integer payStatus;
    /**
     * 支付时间
     */
    @TableField("payTime")
    private Date payTime;
    /**
     * 第三方流水号
     */
    @TableField("orderNumber")
    private String orderNumber;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    @TableField("state")
    private Integer state;
    /**
     * 添加时间
     */
    @TableField("insertTime")
    private Date insertTime;
    public static String CODE(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        return sdf.format(new Date()) + UUIDUtil.getNumberRandom(3);
    }
}
cloud-server-account/src/main/java/com/dsh/account/feignclient/course/model/QueryStoreList.java
New file
@@ -0,0 +1,22 @@
package com.dsh.account.feignclient.course.model;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/28 9:08
 */
@Data
public class QueryStoreList {
    private String provinceCode;
    private String cityCode;
    public QueryStoreList() {
    }
    public QueryStoreList(String provinceCode, String cityCode) {
        this.provinceCode = provinceCode;
        this.cityCode = cityCode;
    }
}
cloud-server-account/src/main/java/com/dsh/account/feignclient/other/StoreClient.java
New file
@@ -0,0 +1,24 @@
package com.dsh.account.feignclient.other;
import com.dsh.account.feignclient.course.model.QueryStoreList;
import com.dsh.account.feignclient.other.model.Store;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 15:54
 */
@FeignClient(value = "mb-cloud-other")
public interface StoreClient {
    /**
     * 获取门店列表
     * @return
     */
    @PostMapping("/store/queryStoreList")
    List<Store> queryStoreList(QueryStoreList queryStoreList);
}
cloud-server-account/src/main/java/com/dsh/account/feignclient/other/model/Store.java
New file
@@ -0,0 +1,94 @@
package com.dsh.account.feignclient.other.model;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author zhibing.pu
 * @date 2023/6/24 15:55
 */
@Data
public class Store {
    private Integer id;
    /**
     * 门店名称
     */
    private String name;
    /**
     * 门店店长id
     */
    private Integer storeStaffId;
    /**
     * 城市管理员id
     */
    private Integer cityManagerId;
    /**
     * 省
     */
    private String province;
    /**
     * 省编号
     */
    private String provinceCode;
    /**
     * 市
     */
    private String city;
    /**
     * 市编号
     */
    private String cityCode;
    /**
     * 联系电话
     */
    private String phone;
    /**
     * 详细地址
     */
    private String address;
    /**
     * 纬度
     */
    private String lat;
    /**
     * 经度
     */
    private String lon;
    /**
     * 营业开始时间
     */
    private String startTime;
    /**
     * 营业结束时间
     */
    private String endTime;
    /**
     * 封面图
     */
    private String coverDrawing;
    /**
     * 实景图
     */
    private String realPicture;
    /**
     * 门店介绍
     */
    private String introduce;
    /**
     * 福利图片
     */
    private String welfarePicture;
    /**
     * 开始上课图片
     */
    private String classPicture;
    /**
     * 评分
     */
    private BigDecimal score;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    private Integer state;
}
cloud-server-account/src/main/java/com/dsh/account/mapper/TAppUserMapper.java
@@ -14,4 +14,10 @@
 */
public interface TAppUserMapper extends BaseMapper<TAppUser> {
    /**
     * 定时任务修改到期会员的状态
     */
    void membershipEnd();
}
cloud-server-account/src/main/java/com/dsh/account/mapper/VipPaymentMapper.java
New file
@@ -0,0 +1,11 @@
package com.dsh.account.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsh.account.entity.VipPayment;
/**
 * @author zhibing.pu
 * @date 2023/6/24 10:02
 */
public interface VipPaymentMapper extends BaseMapper<VipPayment> {
}
cloud-server-account/src/main/java/com/dsh/account/model/JoinPlayPaiVo.java
New file
@@ -0,0 +1,22 @@
package com.dsh.account.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/24 15:36
 */
@Data
public class JoinPlayPaiVo {
    @ApiModelProperty("是否是年度会员(0=否,1=是)")
    private Integer isVip;
    @ApiModelProperty("门店id")
    private Integer storeId;
    @ApiModelProperty("门店名称")
    private String name;
    @ApiModelProperty("门店经度")
    private String lon;
    @ApiModelProperty("门店纬度")
    private String lat;
}
cloud-server-account/src/main/java/com/dsh/account/service/IVipPaymentService.java
New file
@@ -0,0 +1,29 @@
package com.dsh.account.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsh.account.entity.VipPayment;
import com.dsh.account.util.ResultUtil;
/**
 * @author zhibing.pu
 * @date 2023/6/24 10:03
 */
public interface IVipPaymentService extends IService<VipPayment> {
    /**
     * 购买年度会员
     * @param uid
     * @return
     * @throws Exception
     */
    ResultUtil addVipPayment(Integer uid, Integer payType) throws Exception;
    /**
     * 购买年度会员回调处理
     * @throws Exception
     */
    ResultUtil addVipPaymentCallback(String code, String orderNumber) throws Exception;
}
cloud-server-account/src/main/java/com/dsh/account/service/TAppUserService.java
@@ -2,6 +2,7 @@
import com.dsh.account.entity.TAppUser;
import com.dsh.account.model.AddAppUserVo;
import com.dsh.account.model.JoinPlayPaiVo;
import com.dsh.account.model.LoginSMSCodeVo;
import com.dsh.account.model.LoginWeChatVo;
import com.dsh.account.model.vo.classDetails.classInsVo.ClassInfoVo;
@@ -74,4 +75,20 @@
     * @throws Exception
     */
    ResultUtil updatePassword(String phone, String code, String password) throws Exception;
    /**
     * 定时任务修改到期会员的状态
     */
    void membershipEnd();
    /**
     * 获取加入玩湃首页数据
     * @param lon
     * @param lat
     * @return
     * @throws Exception
     */
    JoinPlayPaiVo queryJoinPlayPai(Integer uid, String lon, String lat) throws Exception;
}
cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java
@@ -8,12 +8,16 @@
import com.dsh.account.enums.WeeksEnum;
import com.dsh.account.feignclient.course.CoursePaymentClient;
import com.dsh.account.feignclient.course.model.CourseOfStoreVo;
import com.dsh.account.feignclient.course.model.QueryStoreList;
import com.dsh.account.feignclient.course.model.StuCourseResp;
import com.dsh.account.feignclient.other.ImgConfigClient;
import com.dsh.account.feignclient.other.StoreClient;
import com.dsh.account.feignclient.other.model.Store;
import com.dsh.account.feignclient.other.model.TImgConfig;
import com.dsh.account.mapper.TAppUserMapper;
import com.dsh.account.mapper.TStudentMapper;
import com.dsh.account.model.AddAppUserVo;
import com.dsh.account.model.JoinPlayPaiVo;
import com.dsh.account.model.LoginSMSCodeVo;
import com.dsh.account.model.LoginWeChatVo;
import com.dsh.account.model.vo.classDetails.CourseVenue;
@@ -29,6 +33,7 @@
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -45,7 +50,7 @@
public class TAppUserServiceImpl extends ServiceImpl<TAppUserMapper, TAppUser> implements TAppUserService {
    @Autowired
    @Resource
    private TStudentMapper tsmapper;
    @Resource
@@ -63,8 +68,11 @@
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    @Resource
    private CoursePaymentClient paymentClient;
    @Resource
    private StoreClient storeClient;
@@ -245,6 +253,7 @@
                tAppUser.setCityCode(cityCode);
            }
        }
        tAppUser.setInsertTime(new Date());
        this.baseMapper.insert(tAppUser);
        return ResultUtil.success();
    }
@@ -346,6 +355,7 @@
                        tAppUser.setCityCode(cityCode);
                    }
                }
                tAppUser.setInsertTime(new Date());
                this.baseMapper.insert(tAppUser);
            }
        }
@@ -403,4 +413,50 @@
        this.updateById(tAppUser);
        return ResultUtil.success();
    }
    /**
     * 定时任务修改到期会员的状态
     */
    @Override
    public void membershipEnd() {
        this.baseMapper.membershipEnd();
    }
    /**
     * 获取加入玩湃首页数据
     * @param lon
     * @param lat
     * @return
     * @throws Exception
     */
    @Override
    public JoinPlayPaiVo queryJoinPlayPai(Integer uid, String lon, String lat) throws Exception {
        TAppUser appUser = this.getById(uid);
        JoinPlayPaiVo joinPlayPaiVo = new JoinPlayPaiVo();
        joinPlayPaiVo.setIsVip(appUser.getIsVip());
        Map<String, String> geocode = gdMapGeocodingUtil.geocode(lon, lat);
        if(null != geocode){
            String provinceCode = geocode.get("provinceCode");
            String cityCode = geocode.get("cityCode");
            List<Store> stores = storeClient.queryStoreList(new QueryStoreList(provinceCode, cityCode));
            Store s = null;
            Double d = 0D;
            for (Store store : stores) {
                Map<String, Double> distance = GeodesyUtil.getDistance(lon + "," + lat, store.getLon() + "," + store.getLat());
                Double wgs84 = distance.get("WGS84");
                if(s == null || d.compareTo(wgs84) < 0){
                    s = store;
                    d = wgs84;
                }
            }
            joinPlayPaiVo.setName(s.getName());
            joinPlayPaiVo.setLon(s.getLon());
            joinPlayPaiVo.setLat(s.getLat());
            joinPlayPaiVo.setStoreId(s.getId());
        }
        return joinPlayPaiVo;
    }
}
cloud-server-account/src/main/java/com/dsh/account/service/impl/VipPaymentServiceImpl.java
New file
@@ -0,0 +1,260 @@
package com.dsh.account.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.account.entity.TAppUser;
import com.dsh.account.entity.VipPayment;
import com.dsh.account.mapper.VipPaymentMapper;
import com.dsh.account.service.IVipPaymentService;
import com.dsh.account.service.TAppUserService;
import com.dsh.account.util.PayMoneyUtil;
import com.dsh.account.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
/**
 * @author zhibing.pu
 * @date 2023/6/24 10:03
 */
@Service
public class VipPaymentServiceImpl extends ServiceImpl<VipPaymentMapper, VipPayment> implements IVipPaymentService {
    @Autowired
    private TAppUserService appUserService;
    @Autowired
    private PayMoneyUtil payMoneyUtil;
    /**
     * 购买年度会员
     * @param uid
     * @return
     * @throws Exception
     */
    @Override
    public ResultUtil addVipPayment(Integer uid, Integer payType) throws Exception {
        VipPayment vipPayment = new VipPayment();
        vipPayment.setCode(VipPayment.CODE());
        vipPayment.setAmount(199D);
        vipPayment.setAppUserId(uid);
        vipPayment.setInsertTime(new Date());
        vipPayment.setPayStatus(1);
        vipPayment.setState(1);
        this.baseMapper.insert(vipPayment);
        if(payType == 1){//微信
            return weixinpay(vipPayment);
        }
        if(payType == 2){//支付宝
            return alipay(vipPayment);
        }
        return ResultUtil.success();
    }
    /**
     * 微信
     * @param vipPayment
     * @return
     * @throws Exception
     */
    public ResultUtil weixinpay(VipPayment vipPayment) throws Exception{
        String code = vipPayment.getCode();
        ResultUtil weixinpay = payMoneyUtil.weixinpay("购买年度会员", "", code, vipPayment.getAmount().toString(),
                "/base/appUser/addVipPaymentWeChatCallback", "APP");
        if(weixinpay.getCode() == 200){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        int num = 1;
                        int wait = 0;
                        while (num <= 10){
                            int min = 5000;
                            wait += (min * num);
                            VipPayment vipPayment1 = VipPaymentServiceImpl.this.getOne(new QueryWrapper<VipPayment>().eq("code", code));
                            if(vipPayment1.getPayStatus() != 1){
                                return;
                            }
                            /**
                             * SUCCESS--支付成功
                             * REFUND--转入退款
                             * NOTPAY--未支付
                             * CLOSED--已关闭
                             * REVOKED--已撤销(刷卡支付)
                             * USERPAYING--用户支付中
                             * PAYERROR--支付失败(其他原因,如银行返回失败)
                             * ACCEPT--已接收,等待扣款
                             */
                            ResultUtil<Map<String, String>> resultUtil = payMoneyUtil.queryWXOrder(code, "");
                            if(resultUtil.getCode() == 200){
                                Map<String, String> map = resultUtil.getData();
                                String trade_type = map.get("trade_type");
                                String trade_state = map.get("trade_state");
                                String transaction_id = map.get("transaction_id");
                                if("REFUND".equals(trade_state) || "NOTPAY".equals(trade_state) || "CLOSED".equals(trade_state) || "REVOKED".equals(trade_state) || "PAYERROR".equals(trade_state)){
                                    vipPayment1.setState(3);
                                    VipPaymentServiceImpl.this.updateById(vipPayment1);
                                    return;
                                }
                                if("SUCCESS".equals(trade_state)){
                                    vipPayment1.setPayStatus(2);
                                    vipPayment1.setPayTime(new Date());
                                    vipPayment1.setOrderNumber(transaction_id);
                                    VipPaymentServiceImpl.this.updateById(vipPayment1);
                                    TAppUser appUser = appUserService.getById(vipPayment1.getAppUserId());
                                    Date vipEndTime = appUser.getVipEndTime();
                                    if(null == vipEndTime){
                                        vipEndTime = new Date();
                                    }
                                    Calendar calendar = Calendar.getInstance();
                                    calendar.setTime(vipEndTime);
                                    calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1);
                                    appUser.setVipEndTime(calendar.getTime());
                                    appUserService.updateById(appUser);
                                    return;
                                }
                                if("USERPAYING".equals(trade_state) || "ACCEPT".equals(trade_state)){
                                    Thread.sleep(wait);
                                    num++;
                                }
                            }else{
                                Thread.sleep(wait);
                                num++;
                            }
                            if(10 == num){
                                vipPayment1.setState(3);
                                VipPaymentServiceImpl.this.updateById(vipPayment1);
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        return weixinpay;
    }
    /**
     * 支付宝
     * @param vipPayment
     * @return
     * @throws Exception
     */
    public ResultUtil alipay(VipPayment vipPayment) throws Exception{
        String code = vipPayment.getCode();
        ResultUtil alipay = payMoneyUtil.alipay("购买年度会员", "", code, vipPayment.getAmount().toString(),
                "/base/appUser/addVipPaymentAliCallback");
        if(alipay.getCode() == 200){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        int num = 1;
                        int wait = 0;
                        while (num <= 10){
                            int min = 5000;
                            wait += (min * num);
                            VipPayment vipPayment1 = VipPaymentServiceImpl.this.getOne(new QueryWrapper<VipPayment>().eq("code", code));
                            if(vipPayment1.getPayStatus() != 1){
                                return;
                            }
                            /**
                             * 交易状态:
                             * WAIT_BUYER_PAY(交易创建,等待买家付款)、
                             * TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、
                             * TRADE_SUCCESS(交易支付成功)、
                             * TRADE_FINISHED(交易结束,不可退款)
                             */
                            ResultUtil<Map<String, String>> resultUtil = payMoneyUtil.queryALIOrder(code);
                            if(resultUtil.getCode() == 200){
                                Map<String, String> map = resultUtil.getData();
                                String tradeStatus = map.get("tradeStatus");
                                String tradeNo = map.get("tradeNo");
                                if("TRADE_CLOSED".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){
                                    vipPayment1.setState(3);
                                    VipPaymentServiceImpl.this.updateById(vipPayment1);
                                    return;
                                }
                                if("TRADE_SUCCESS".equals(tradeStatus)){
                                    vipPayment1.setPayStatus(2);
                                    vipPayment1.setPayTime(new Date());
                                    vipPayment1.setOrderNumber(tradeNo);
                                    VipPaymentServiceImpl.this.updateById(vipPayment1);
                                    TAppUser appUser = appUserService.getById(vipPayment1.getAppUserId());
                                    Date vipEndTime = appUser.getVipEndTime();
                                    if(null == vipEndTime){
                                        vipEndTime = new Date();
                                    }
                                    Calendar calendar = Calendar.getInstance();
                                    calendar.setTime(vipEndTime);
                                    calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1);
                                    appUser.setVipEndTime(calendar.getTime());
                                    appUserService.updateById(appUser);
                                    return;
                                }
                                if("WAIT_BUYER_PAY".equals(tradeStatus)){
                                    Thread.sleep(wait);
                                    num++;
                                }
                            }else{
                                Thread.sleep(wait);
                                num++;
                            }
                            if(10 == num){
                                vipPayment1.setState(3);
                                VipPaymentServiceImpl.this.updateById(vipPayment1);
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        return alipay;
    }
    /**
     * 购买年度会员支付回调处理
     * @param code
     * @param orderNumber
     * @throws Exception
     */
    @Override
    public ResultUtil addVipPaymentCallback(String code, String orderNumber) throws Exception {
        VipPayment vipPayment1 = VipPaymentServiceImpl.this.getOne(new QueryWrapper<VipPayment>().eq("code", code));
        if(vipPayment1.getPayStatus() != 1){
            return ResultUtil.success();
        }
        vipPayment1.setPayStatus(2);
        vipPayment1.setPayTime(new Date());
        vipPayment1.setOrderNumber(orderNumber);
        VipPaymentServiceImpl.this.updateById(vipPayment1);
        TAppUser appUser = appUserService.getById(vipPayment1.getAppUserId());
        Date vipEndTime = appUser.getVipEndTime();
        if(null == vipEndTime){
            vipEndTime = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(vipEndTime);
        calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1);
        appUser.setVipEndTime(calendar.getTime());
        appUserService.updateById(appUser);
        return ResultUtil.success();
    }
}
cloud-server-account/src/main/java/com/dsh/account/util/GDMapGeocodingUtil.java
@@ -21,9 +21,6 @@
    private String key = "fb131ad2dbfb3f39d7d37d244b92aa2d";
    @Autowired
    private HttpClientUtil httpClientUtil;
    /**
     * 将行政区域名称转化为坐标
@@ -53,12 +50,10 @@
        String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON";
        url += "&address=" + province + (ToolUtil.isNotEmpty(city) ? city : "") + (ToolUtil.isNotEmpty(county) ? county : "") + (ToolUtil.isNotEmpty(address) ? address : "");
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        String status = jsonObject.getString("status");
        List<String> list = new ArrayList<>();
//        gdInterfaceService.saveData("https://restapi.amap.com/v3/geocode/geo", "行政区域转经纬度");
        if(status.equals("1")){
            JSONArray geocodes = jsonObject.getJSONArray("geocodes");
@@ -77,12 +72,10 @@
    public Map<String, Object> geocoding(String address) throws Exception{
        Map<String, Object> map = new HashMap<>();
        String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON&address=" + address;
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        String status = jsonObject.getString("status");
        List<String> list = new ArrayList<>();
//        gdInterfaceService.saveData("https://restapi.amap.com/v3/geocode/geo", "行政区域转经纬度");
        if(status.equals("1")){
            JSONArray geocodes = jsonObject.getJSONArray("geocodes");
@@ -107,11 +100,9 @@
     */
    public Map<String, String> geocode(String lon, String lan) throws Exception{
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + key + "&location=" + lon + "," + lan;
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        Map<String, String> map = new HashMap<>();
//        gdInterfaceService.saveData("https://restapi.amap.com/v3/geocode/regeo", "经纬度转行政区域");
        if(jsonObject.getString("status").equals("1")){
            JSONObject regeocode = jsonObject.getJSONObject("regeocode");
@@ -142,7 +133,7 @@
     */
    public Map<String, String> convert(String locations, String coordsys) throws Exception{
        String url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + locations + "&coordsys=" + coordsys + "&output=json&key=" + key;
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        Map<String, String> map = new HashMap<>();
        if("1".equals(jsonObject.getString("status"))){
cloud-server-account/src/main/java/com/dsh/account/util/GeodesyUtil.java
New file
@@ -0,0 +1,63 @@
package com.dsh.account.util;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import java.util.HashMap;
import java.util.Map;
/**
 * 计算两个金纬度坐标之间的直线距离
 */
public class GeodesyUtil {
    /**
     * 获取直线距离
     * @param fromLonLat
     * @param toLonLat
     * @return
     */
    public static Map<String, Double> getDistance(String fromLonLat, String toLonLat){
        String[] from = fromLonLat.split(",");
        String[] to = toLonLat.split(",");
        GlobalCoordinates source = new GlobalCoordinates(Double.valueOf(from[1]), Double.valueOf(from[0]));
        GlobalCoordinates target = new GlobalCoordinates(Double.valueOf(to[1]), Double.valueOf(to[0]));
        double Sphere = getDistanceMeter(source, target, Ellipsoid.Sphere);
        double WGS84 = getDistanceMeter(source, target, Ellipsoid.WGS84);
        double GRS80 = getDistanceMeter(source, target, Ellipsoid.GRS80);
        double GRS67 = getDistanceMeter(source, target, Ellipsoid.GRS67);
        double ANS = getDistanceMeter(source, target, Ellipsoid.ANS);
        double WGS72 = getDistanceMeter(source, target, Ellipsoid.WGS72);
        double Clarke1858 = getDistanceMeter(source, target, Ellipsoid.Clarke1858);
        double Clarke1880 = getDistanceMeter(source, target, Ellipsoid.Clarke1880);
//        System.out.println("Sphere坐标系计算结果:"+Sphere + "米");
//        System.out.println("WGS84坐标系计算结果:"+WGS84 + "米");
//        System.out.println("GRS80坐标系计算结果:"+GRS80 + "米");
//        System.out.println("GRS67坐标系计算结果:"+GRS67 + "米");
//        System.out.println("ANS坐标系计算结果:"+ANS + "米");
//        System.out.println("WGS72坐标系计算结果:"+WGS72 + "米");
//        System.out.println("Clarke1858坐标系计算结果:"+Clarke1858 + "米");
//        System.out.println("Clarke1880坐标系计算结果:"+Clarke1880 + "米");
        Map<String, Double> map = new HashMap<>();
        map.put("Sphere", Sphere);
        map.put("WGS84", WGS84);
        map.put("GRS80", GRS80);
        map.put("GRS67", GRS67);
        map.put("ANS", ANS);
        map.put("WGS72", WGS72);
        map.put("Clarke1858", Clarke1858);
        map.put("Clarke1880", Clarke1880);
        return map;
    }
    private static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid){
        //创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);
        return geoCurve.getEllipsoidalDistance();
    }
}
cloud-server-account/src/main/java/com/dsh/account/util/MD5AndKL.java
New file
@@ -0,0 +1,112 @@
package com.dsh.account.util;
import java.security.MessageDigest;
public class MD5AndKL {
    /**
     * MD5加码。32位
     *
     * @param inStr
     * @return
     */
    public static String MD5(String inStr) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            throw new RuntimeException(e.toString());
        }
        byte[] md5Bytes = md5.digest(inStr.getBytes());
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }
    /**
     * 可逆的加密算法
     *
     * @param inStr
     * @return
     */
    public static String KL(String inStr) {
        char[] a = inStr.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String s = new String(a);
        return s;
    }
    /**
     * 加密后解密
     *
     * @param inStr
     * @return
     */
    public static String JM(String inStr) {
        char[] a = inStr.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String k = new String(a);
        return k;
    }
    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));
        return resultSb.toString();
    }
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }
    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname)){
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            }else{
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return resultString;
    }
    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    public static void main(String args[]) {
        System.out.println("MD5后再加密:" + KL(MD5("123456")));
        System.out.println(MD5("123456"));
        // System.out.println("加密:" + KL(MD5("123456")));
        // s = KL(s);
        // System.out.println("解密:" + KL("81dc9bdb52d04dc20036dbd8313ed055"));
        // System.out.println("解密:" + JM(KL(s)));
        // System.out.println("解密为MD5后的:" + KL(KL(MD5(s))));
        // System.out.println(JM("5d62957bb57d3e49dcf48a0df064be4c"));
        // System.out.println(MD5AndKL.KL(MD5AndKL.MD5("admin"+"87654321")));
    }
}
cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java
New file
@@ -0,0 +1,803 @@
package com.dsh.account.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.dsh.account.util.httpClinet.HttpClientUtil;
import org.apache.commons.collections.map.HashedMap;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.*;
import java.util.*;
/**
 * 第三方支付工具类
 */
@Component
public class PayMoneyUtil {
    //支付宝appid
    private String aliAppid = "";
    //支付宝开发者应用私钥
    private String appPrivateKey = "";
    //支付宝应用公钥
    private String alipayPublicKey = "";
    //支付宝支付公钥
    private String alipay_public_key = "";
    //微信appid
    private String appid = "";
    //微信商户号
    private String mchId = "";
    //微信商户号
    private String key = "";
    //支付回调网关地址
    @Value("${callbackPath}")
    private String callbackPath;
    //微信支付证书地址
    private String wechatPayCertificatesFromPath = "/usr/local/server/app/cert/weixin/apiclient_cert.p12";
    //微信私钥证书地址
    private String privateKeyFromPath = "/usr/local/server/app/cert/weixin/apiclient_cert.pem";
    /**
     * 支付宝支付
     */
    public ResultUtil<String> alipay(String body, String subject, String outTradeNo, String amount, String notifyUrl){
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipayPublicKey, "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(body);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
        model.setSubject(subject);//商品的标题/交易标题/订单标题/订单关键字等。
        model.setOutTradeNo(outTradeNo);//商户网站唯一订单号
        model.setTimeoutExpress("30m");
        model.setTotalAmount(amount);//付款金额
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(callbackPath + notifyUrl);
        try {
            //这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
            return ResultUtil.success(response.getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return ResultUtil.error("调起支付异常", "");
        }
    }
    /**
     * 支付宝扫码支付下单
     * @param body
     * @param subject
     * @param outTradeNo
     * @param amount
     * @param notifyUrl
     * @return
     */
    public ResultUtil aliScanCodePay(String body, String subject, String outTradeNo, String amount, String notifyUrl){
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); //获得初始化的AlipayClient
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//创建API对应的request类
        request.setBizContent("{" +
                "    \"out_trade_no\":\"" + outTradeNo + "\"," +//商户订单号
                "    \"total_amount\":\"" + 1 + "\"," +
                "    \"subject\":\"" + subject + "\"," +
                "    \"notify_url\":\"" + callbackPath + notifyUrl + "\"," +
                "    \"body\":\"" + body + "\"," +
                "    \"store_id\":\"NJ_001\"," +
                "    \"timeout_express\":\"90m\"}");//订单允许的最晚付款时间
        AlipayTradePrecreateResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        JSONObject alipay_trade_precreate_response = JSON.parseObject(response.getBody()).getJSONObject("alipay_trade_precreate_response");
        System.err.print(alipay_trade_precreate_response.getString("qr_code"));
        return ResultUtil.success(alipay_trade_precreate_response.getString("qr_code"));
    }
    /**
     * 支付成功后的回调处理逻辑
     * @param request
     */
    public Map<String, String> alipayCallback(HttpServletRequest request){
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
//        try {
//            boolean flag = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8","RSA2");
//            if(flag){
                Map<String, String> map = new HashMap<>();
                String out_trade_no = params.get("out_trade_no");
                String subject = params.get("subject");
                String total_amount = params.get("total_amount");
                String trade_no = params.get("trade_no");
                map.put("out_trade_no", out_trade_no);//商家订单号
                map.put("subject", subject);
                map.put("total_amount", total_amount);
                map.put("trade_no", trade_no);//支付宝交易号
                return map;
//            }
//        } catch (AlipayApiException e) {
//            e.printStackTrace();
//        }
//        return null;
    }
    /**
     * 支付宝查询订单支付状态
     * @param out_trade_no
     * @return
     * @throws Exception
     */
    public ResultUtil<Map<String, String>> queryALIOrder(String out_trade_no) throws Exception{
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2");
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":\"" + out_trade_no +
                "\"}");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            String tradeStatus = response.getTradeStatus();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)
            String tradeNo = response.getTradeNo();
            Map<String, String> map = new HashMap<>();
            map.put("tradeStatus", tradeStatus);
            map.put("tradeNo", tradeNo);
            return ResultUtil.success(map);
        } else {
            return ResultUtil.error(response.getMsg());
        }
    }
    /**
     * 微信统一下单
     * @param body          商品描述
     * @param attach        附加数据
     * @param out_trade_no  商户订单号
     * @param total_fee     标价金额
     * @param notify_url    通知地址
     * @param tradeType     交易类型
     * @return
     */
    public ResultUtil weixinpay(String body, String attach, String out_trade_no, String total_fee, String notify_url, String tradeType) throws Exception{
        int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        String hostAddress = null;
        try {
            hostAddress = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String nonce_str = UUIDUtil.getRandomCode(16);
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);
        map.put("body", body);
        map.put("attach", attach);//存储订单id
        map.put("out_trade_no", out_trade_no);//存储的订单code
        map.put("total_fee", i);
        map.put("spbill_create_ip", hostAddress);
        map.put("notify_url", callbackPath + notify_url);
        map.put("trade_type", tradeType);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                String type = map1.get("trade_type");
                switch (type){
                    case "JSAPI":
                        break;
                    case "NATIVE":
                        String code_url = map1.get("code_url");
                        return ResultUtil.success(code_url);
                    case "APP":
                        String prepay_id = map1.get("prepay_id");
                        //重新进行签名后返回给前端
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("appid", appid);
                        map2.put("noncestr", nonce_str);
                        map2.put("package", "Sign=WXPay");
                        map2.put("partnerid", mchId);
                        map2.put("prepayid", prepay_id);
                        map2.put("timestamp", new Date().getTime() / 1000);
                        String s1 = this.weixinSignature(map2);
                        map2.put("sign", s1);
                        System.err.println(map2);
                        return ResultUtil.success(map2);
                }
                return null;
            }else{
                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    /**
     * 微信支付成功后的回调处理
     * @param request
     */
    public Map<String, String> weixinpayCallback(HttpServletRequest request){
        try {
            String param = this.getParam(request);
            param = param.replaceAll("<!\\[CDATA\\[","");
            param = param.replaceAll("]]>", "");
            Map<String, String> map = this.xmlToMap(param, "UTF-8");
            String return_code = map.get("return_code");
            if("SUCCESS".equals(return_code)){
                String result_code = map.get("result_code");
                if("SUCCESS".equals(result_code)){
                    Map<String, String> map1 = new HashedMap();
                    map1.put("nonce_str", map.get("nonce_str"));
                    map1.put("out_trade_no", map.get("out_trade_no"));
                    map1.put("attach", map.get("attach"));
                    map1.put("total_fee", map.get("total_fee"));
                    map1.put("transaction_id", map.get("transaction_id"));//微信支付订单号
                    String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                    map1.put("result", result);
                    return map1;
                }else{
                    System.err.println(map.get("err_code_des"));
                }
            }else{
                System.err.println(map.get("return_msg"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 微信扫码收款
     * @param body              商品描述
     * @param attach            附加数据
     * @param nonce_str         随机字符串
     * @param out_trade_no      商户订单号
     * @param total_fee         订单金额
     * @param auth_code         授权码    扫码支付授权码,设备读取用户微信中的条码或者二维码信息(注:用户付款码条形码规则:18位纯数字,以10、11、12、13、14、15开头)
     * @return
     */
    public ResultUtil wxScanQRCodePay(String body, String attach, String nonce_str, String out_trade_no, String total_fee, String auth_code){
        int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        String hostAddress = null;
        try {
            InetAddress address = InetAddress.getLocalHost();
            hostAddress = address.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String randomCode = null;
        try {
            randomCode = UUIDUtil.getRandomCode(10);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);//存储的支付人员id,员工扫描二维码支付的时候存储的是收款员工id
        map.put("body", body);
        map.put("attach", attach);//存储的费用月份数据,员工扫描二维码支付的时候存储的是收费项id
        map.put("out_trade_no", randomCode + "_" + out_trade_no);//存储的房间id
        map.put("total_fee", i);
        map.put("spbill_create_ip", hostAddress);
        map.put("auth_code", auth_code);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = null;
        try {
            body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                String type = map1.get("trade_type");
                switch (type){
                    case "JSAPI":
                        break;
                    case "NATIVE":
                        String code_url = map1.get("code_url");
                        return ResultUtil.success(code_url);
                    case "APP":
                        String prepay_id = map1.get("prepay_id");
                        //重新进行签名后返回给前端
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("appid", appid);
                        map2.put("noncestr", nonce_str);
                        map2.put("package", "Sign=WXPay");
                        map2.put("partnerid", mchId);
                        map2.put("prepayid", prepay_id);
                        map2.put("timestamp", new Date().getTime() + "");
                        String s1 = this.weixinSignature(map2);
                        map2.put("pac", "Sign=WXPay");
                        map2.put("sign", s1);
//                      System.err.println(map2);
                        return ResultUtil.success(map2);
                }
                return null;
            }else{
//                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
//            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    /**
     * 支付宝扫码收款
     * @param data
     * @return
     */
    public Object aliScanQRCodePay(String data){
        return null;
    }
    /**
     * 微信退款申请
     * @param transaction_id    微信订单号。微信生成的订单号,在支付通知中有返回
     * @param out_refund_no     商户退款单号。商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
     * @param total_fee         订单金额。订单总金额,单位为分,只能为整数
     * @param refund_fee        退款金额。退款总金额,订单总金额,单位为分,只能为整数
     * @param notify_url        退款结果通知url。异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。
     * @return
     */
    public Map<String, String> wxRefund(String transaction_id, String out_refund_no, String total_fee, String refund_fee, String notify_url){
        int tf = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        int rf = new BigDecimal(refund_fee).multiply(new BigDecimal("100")).intValue();
        String nonce_str = UUIDUtil.getRandomCode();
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);
        map.put("transaction_id", transaction_id);
        map.put("out_refund_no", out_refund_no);
        map.put("total_fee", tf);
        map.put("refund_fee", rf);
        map.put("notify_url", callbackPath + notify_url);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = null;
        try {
            body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        Map<String, String> map2 = new HashMap<>();
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                map2.put("return_code", result_code);
                map2.put("refund_id", String.valueOf(map1.get("refund_id")));//微信退款订单号
                map2.put("refund_fee", String.valueOf(map1.get("refund_fee")));//退款金额
                return map2;
            }else{
                map2.put("return_code", result_code);
                map2.put("return_msg", map1.get("err_code_des"));
                return map2;
            }
        }else{
            map2.put("return_code", return_code);
            map2.put("return_msg", map1.get("return_msg"));
            return map2;
        }
    }
    /**
     * 微信退款成功后的回调处理
     * @param request
     * @return
     */
    public Map<String, String> wxRefundCallback(HttpServletRequest request){
        try {
            String param = this.getParam(request);
            param = param.replaceAll("<!\\[CDATA\\[","");
            param = param.replaceAll("]]>", "");
            Map<String, String> map = this.xmlToMap(param, "UTF-8");
            String return_code = map.get("return_code");
            if("SUCCESS".equals(return_code)){
                String req_info = map.get("req_info");//加密信息请用商户秘钥进行解密
                String s = this.wxDecrypt(req_info);
                s = s.replaceAll("<!\\[CDATA\\[","");
                s = s.replaceAll("]]>", "");
                map = this.xmlToMap(s, "UTF-8");
                Map<String, String> map1 = new HashMap<>();
                map1.put("refund_id", map.get("refund_id"));
                map1.put("out_refund_no", map.get("out_refund_no"));
                return map1;
            }else{
//                System.err.println(map.get("return_msg"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 支付宝退款
     * @param trade_no          支付宝交易号
     * @param refund_amount     退款金额
     * @return
     * @throws AlipayApiException
     */
    public Map<String, String> aliRefund(String trade_no, String refund_amount) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("trade_no", trade_no);
        jsonObject.put("refund_amount", refund_amount);
        request.setBizContent(jsonObject.toJSONString());
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        Map<String, String> map = new HashMap<>();
        if(response.isSuccess()){
            System.out.println("调用成功");
            String outTradeNo = response.getOutTradeNo();
            map.put("code", response.getCode());//10000
            map.put("trade_no", response.getTradeNo());//支付宝交易号
            map.put("out_trade_no", outTradeNo);//商户订单号
        } else {
            System.out.println("调用失败");
            map.put("code", response.getCode());
            map.put("msg", response.getSubMsg());
        }
        return map;
    }
    /**
     * 查询微信支付订单
     * @return
     * @throws Exception
     */
    public ResultUtil<Map<String, String>> queryWXOrder(String out_trade_no, String transaction_id) throws Exception{
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";
        String nonce_str = UUIDUtil.getRandomCode(16);
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("out_trade_no", out_trade_no);//商户订单号
        map.put("transaction_id", transaction_id);//微信订单号
        map.put("nonce_str", nonce_str);//随机字符串
        String s = this.weixinSignature(map);
        map.put("sign", s);
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                Map<String, String> map2 = new HashMap<>();
                map2.put("trade_type", map1.get("trade_type"));
                map2.put("trade_state", map1.get("trade_state"));//订单状态SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败)
                map2.put("transaction_id", map1.get("transaction_id"));
                return ResultUtil.success(map2);
            }else{
                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"));
        }
    }
    /**
     * 获取请求内容
     * @param request
     * @return
     * @throws IOException
     */
    private String getParam(HttpServletRequest request) throws IOException {
        // 读取参数
        InputStream inputStream;
        StringBuilder sb = new StringBuilder();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        return sb.toString();
    }
    /**
     * 微信下单的签名算法
     * @param map
     * @return
     */
    private String weixinSignature(Map<String, Object> map){
        try {
            Set<Map.Entry<String, Object>> entries = map.entrySet();
            List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries);
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
                public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, Object> 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=" + key);
            String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式
            return sign;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 微信退款成功后的解密
     * @param req_info
     * @return
     */
    private String wxDecrypt(String req_info) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        byte[] decode = Base64.getDecoder().decode(req_info);
        String sign = MD5AndKL.MD5Encode(key, "UTF-8").toLowerCase();
        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));
    }
    public static void main(String[] ages){
//        PayMoneyUtil payMoneyUtil = new PayMoneyUtil();
//        payMoneyUtil.weixinpay("测试", "123", "12.5", "");
    }
    /**
     * xml转map
     * @param xml
     * @param charset
     * @return
     * @throws UnsupportedEncodingException
     * @throws DocumentException
     */
    public static Map<String, String> xmlToMap(String xml, String charset) throws UnsupportedEncodingException, DocumentException {
        Map<String, String> respMap = new HashMap<String, String>();
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new ByteArrayInputStream(xml.getBytes(charset)));
        Element root = doc.getRootElement();
        xmlToMap(root, respMap);
        return respMap;
    }
    public static Map<String, String> xmlToMap(Element tmpElement, Map<String, String> respMap){
        if (tmpElement.isTextOnly()) {
            respMap.put(tmpElement.getName(), tmpElement.getText());
            return respMap;
        }
        @SuppressWarnings("unchecked")
        Iterator<Element> eItor = tmpElement.elementIterator();
        while (eItor.hasNext()) {
            Element element = eItor.next();
            xmlToMap(element, respMap);
        }
        return respMap;
    }
}
cloud-server-account/src/main/java/com/dsh/account/util/ResultUtil.java
@@ -107,8 +107,8 @@
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", new JSONObject());
    public static  ResultUtil paranErr(String ages){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "【" + ages + "】参数异常", new JSONObject());
    }
    /**
@@ -116,11 +116,10 @@
     * @return
     */
    public static <T> ResultUtil<T> paranErr(T data){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "SYSTEM_RUN_ERROR", data);
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", data);
    }
    @Autowired
    private static MessageUtils messageUtils;
    /**
     * 运行异常
     * @return
cloud-server-account/src/main/java/com/dsh/account/util/TaskUtil.java
New file
@@ -0,0 +1,43 @@
package com.dsh.account.util;
import com.dsh.account.entity.TAppUser;
import com.dsh.account.service.TAppUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 * @author zhibing.pu
 * @date 2023/6/24 15:26
 */
@Component
public class TaskUtil {
    @Autowired
    private TAppUserService appUserService;
    /**
     * 每隔一分钟去处理的定时任务
     */
    @Scheduled(fixedRate = 1000 * 60)
    public void taskMinute(){
        try {
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 每天的凌晨执行的任务
     */
    @Scheduled(cron = "0 0 0 * * *")
    public void taskDay(){
        try {
            appUserService.membershipEnd();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
cloud-server-account/src/main/java/com/dsh/account/util/TokenUtil.java
@@ -2,6 +2,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@@ -12,7 +14,9 @@
    private RedisUtil redisUtil;
    public Integer getUserIdFormRedis(HttpServletRequest request) throws Exception {
    public Integer getUserIdFormRedis() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String requestHeader = request.getHeader("Authorization");
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            requestHeader = requestHeader.substring(requestHeader.indexOf(" ") + 1);
cloud-server-account/src/main/java/com/dsh/account/util/httpClinet/HttpClientUtil.java
@@ -1,6 +1,7 @@
package com.dsh.account.util.httpClinet;
import com.alibaba.fastjson.JSON;
import com.dsh.account.util.httpClinet.HttpResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
@@ -19,7 +20,6 @@
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.net.ssl.SSLContext;
import java.io.File;
@@ -34,15 +34,14 @@
/**
 * http工具类
 */
@Component
public class HttpClientUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    private PoolingHttpClientConnectionManager connectionManager;
    private static PoolingHttpClientConnectionManager connectionManager;
    public HttpClientUtil(){
    {
        //1.创建连接池管理器
        connectionManager = new PoolingHttpClientConnectionManager(60000,
                TimeUnit.MILLISECONDS);
@@ -53,14 +52,14 @@
    /**
     * 创建一个httpClient对象
     */
    private CloseableHttpClient getHttpCline(){
    private static CloseableHttpClient getHttpCline(){
        return  HttpClients.custom()
                .setConnectionManager(connectionManager)
                .disableAutomaticRetries()
                .build();
    }
    private RequestConfig getRequestConfig(){
    private static RequestConfig getRequestConfig(){
        RequestConfig.Builder builder = RequestConfig.custom();
        builder.setSocketTimeout(60000)//3.1设置客户端等待服务端返回数据的超时时间
                .setConnectTimeout(30000)//3.2设置客户端发起TCP连接请求的超时时间
@@ -76,9 +75,9 @@
     * @param url       请求地址
     * @param params    请求参数
     */
    private CloseableHttpResponse setPostHttpRequset(String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
    private static CloseableHttpResponse setPostHttpRequset(String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(this.getRequestConfig());
        httpPost.setConfig(getRequestConfig());
        if(null != header){
            for(String key : header.keySet()){
                httpPost.setHeader(key, header.get(key));
@@ -110,7 +109,7 @@
     * @param url       请求地址
     * @param params    请求参数
     */
    private CloseableHttpResponse setGetHttpRequset(String url, Map<String, Object> params, Map<String, String> header) throws Exception{
    private static CloseableHttpResponse setGetHttpRequset(String url, Map<String, Object> params, Map<String, String> header) throws Exception{
        StringBuffer sb = new StringBuffer();
        String p = "";
        if(null != params){
@@ -140,14 +139,14 @@
     * @param contentType   参数请求方式form/json
     * @return
     */
    public HttpResult pushHttpRequset(String mothed, String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
    public static HttpResult pushHttpRequset(String mothed, String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
        String randome = UUID.randomUUID().toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
        logger.info(sdf.format(new Date()) + "----(" + randome + ")请求参数:" + JSON.toJSONString(params));
        CloseableHttpResponse httpResponse = null;
        switch (mothed){
            case "GET":
                httpResponse = this.setGetHttpRequset(url, params, header);
                httpResponse = setGetHttpRequset(url, params, header);
                break;
            case "POST":
                httpResponse = setPostHttpRequset(url, params, header, contentType);
@@ -157,7 +156,7 @@
        String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        logger.info(sdf.format(new Date()) + "----(" + randome + ")返回结果:" + content);
        HttpResult httpResult = HttpResult.getHttpResult(statusCode, content);
        this.close(httpResponse);
        close(httpResponse);
        return httpResult;
    }
@@ -169,7 +168,7 @@
     * @param header    自定义请求头
     * @return
     */
    public HttpResult pushHttpRequsetXml(String url, String xml, Map<String, String> header) throws Exception{
    public static HttpResult pushHttpRequsetXml(String url, String xml, Map<String, String> header) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        for(String key : header.keySet()){
@@ -181,7 +180,7 @@
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        HttpResult httpResult = HttpResult.getHttpResult(statusCode, content);
        this.close(httpResponse);
        close(httpResponse);
        return httpResult;
    }
@@ -246,7 +245,7 @@
    /**
     * 关闭资源
     */
    private void close(CloseableHttpResponse httpResponse){
    private static void close(CloseableHttpResponse httpResponse){
        try {
            if(null != httpResponse){
                EntityUtils.consume(httpResponse.getEntity());//此处高能,通过源码分析,由EntityUtils是否回收HttpEntity
cloud-server-account/src/main/java/com/dsh/account/util/weChat/WeChatUtil.java
@@ -45,9 +45,6 @@
    private String webAppSecret;
    @Autowired
    private HttpClientUtil httpClientUtil;
    @Autowired
    private RestTemplate restTemplate;
@@ -59,7 +56,7 @@
    public Map<String, Object> code2Session(String jscode) throws Exception{
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxAppletsAppid + "&secret=" + wxAppletsAppSecret
                + "&js_code=" + jscode + "&grant_type=authorization_code";
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(null == httpResult || httpResult.getCode() != 200){
            return null;
        }
@@ -95,7 +92,7 @@
     */
    public String getWxAppletsAccessToken() throws Exception{
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + wxAppletsAppid + "&secret=" + wxAppletsAppSecret;
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return "";
        }
@@ -111,7 +108,7 @@
     */
    public Map<String, String> webAccessToken(String code) throws Exception{
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + webAppId + "&secret=" + webAppSecret + "&code=" + code + "&grant_type=authorization_code";
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
@@ -149,7 +146,7 @@
     */
    public Map<String, Object> getUserInfo(String access_token, String openid) throws Exception{
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid;
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
@@ -191,7 +188,7 @@
        String grantType = "authorization_code";
        String params = "appid=" + officialAccountAppid + "&secret=" + officialAccountAppSecret + "&code=" + code + "&grant_type=" + grantType;
        System.out.println("sssss"+params);
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", "https://api.weixin.qq.com/sns/oauth2/access_token?" + params, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", "https://api.weixin.qq.com/sns/oauth2/access_token?" + params, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
@@ -220,7 +217,7 @@
    public String getAccessToken() throws Exception{
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + officialAccountAppid
                + "&secret=" + officialAccountAppSecret;
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
@@ -237,7 +234,7 @@
        //获取token
        String acess_token= this.getAccessToken();
        String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + acess_token + "&type=jsapi";
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", urlStr, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", urlStr, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
@@ -280,7 +277,7 @@
     */
    public Map<String, Object> queryUserInfo(String access_token, String openid) throws Exception{
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid + "&lang=zh_CN";
        HttpResult httpResult = httpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
cloud-server-account/src/main/resources/mapper/TAppUserMapper.xml
@@ -31,4 +31,9 @@
        <result column="headImg" property="headImg" />
    </resultMap>
    <update id="membershipEnd">
        update t_app_user set isVip = 0 where isVip = 1 and now() >= vipEndTime
    </update>
</mapper>
cloud-server-account/src/main/resources/mapper/VipPaymentMapper.tld
New file
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dsh.account.mapper.VipPaymentMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.dsh.account.entity.VipPayment">
        <id column="id" property="id" />
        <result column="code" property="code" />
        <result column="appUserId" property="appUserId" />
        <result column="amount" property="amount" />
        <result column="payType" property="payType" />
        <result column="payStatus" property="payStatus" />
        <result column="payTime" property="payTime" />
        <result column="orderNumber" property="orderNumber" />
        <result column="state" property="state" />
        <result column="insertTime" property="insertTime" />
        <result column="isDefault" property="isDefault" />
    </resultMap>
</mapper>
cloud-server-activity/src/main/java/com/dsh/activity/controller/CouponController.java
New file
@@ -0,0 +1,55 @@
package com.dsh.activity.controller;
import com.dsh.activity.model.CouponListVo;
import com.dsh.activity.service.ICouponService;
import com.dsh.activity.util.ResultUtil;
import com.dsh.activity.util.TokenUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 11:27
 */
@RestController
@RequestMapping("")
public class CouponController {
    @Autowired
    private ICouponService couponService;
    @Autowired
    private TokenUtil tokenUtil;
    @ResponseBody
    @PostMapping("/api/coupon/queryCouponList")
    @ApiOperation(value = "获取优惠券列表", tags = {"APP-成为会员", ""})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "1=积分购买,2=注册赠送", name = "distributionMethod", dataType = "int", required = true),
            @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil queryCouponList(@RequestBody Integer distributionMethod){
        if(null == distributionMethod){
            return ResultUtil.paranErr("distributionMethod");
        }
        try {
            Integer uid = tokenUtil.getUserIdFormRedis();
            if(null == uid){
                return ResultUtil.tokenErr();
            }
            List<CouponListVo> listVos = couponService.queryCouponList(uid, distributionMethod);
            return ResultUtil.success(listVos);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.success();
        }
    }
}
cloud-server-activity/src/main/java/com/dsh/activity/entity/Coupon.java
New file
@@ -0,0 +1,144 @@
package com.dsh.activity.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
 * 优惠券
 * @author zhibing.pu
 * @date 2023/6/24 11:04
 */
@Data
@TableName("t_coupon")
public class Coupon {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 优惠券名称
     */
    @TableField("name")
    private String name;
    /**
     * 优惠券类型(1=满减券,2=代金券,3=体验券)
     */
    @TableField("type")
    private Integer type;
    /**
     * 优惠券规则JSON
     */
    @TableField("content")
    private String content;
    /**
     * 优惠券说明
     */
    @TableField("illustrate")
    private String illustrate;
    /**
     * 发放方式(1=积分购买,2=注册赠送,3=自动发券)
     */
    @TableField("distributionMethod")
    private Integer distributionMethod;
    /**
     * 兑换方式(1=积分,2=积分+现金)
     */
    @TableField("redemptionMethod")
    private Integer redemptionMethod;
    /**
     * 所需现金
     */
    @TableField("cash")
    private Double cash;
    /**
     * 所需积分
     */
    @TableField("integral")
    private Integer integral;
    /**
     * 用户人群(1=全部用户,2=年度会员,3=已有学员用户)
     */
    @TableField("userPopulation")
    private Integer userPopulation;
    /**
     * 发放数量
     */
    @TableField("quantityIssued")
    private Integer quantityIssued;
    /**
     * 限领数量
     */
    @TableField("pickUpQuantity")
    private Integer pickUpQuantity;
    /**
     * 开始时间
     */
    @TableField("startTime")
    private Date startTime;
    /**
     * 结束时间
     */
    @TableField("endTime")
    private Date endTime;
    /**
     * 使用范围(1=全国,2=指定城市,3=指定门店)
     */
    @TableField("useScope")
    private Integer useScope;
    /**
     * 省
     */
    @TableField("province")
    private Integer province;
    /**
     * 省编号
     */
    @TableField("provinceCode")
    private String provinceCode;
    /**
     * 市
     */
    @TableField("city")
    private String city;
    /**
     * 市编号
     */
    @TableField("cityCode")
    private String cityCode;
    /**
     * 审核状态(1=待审核,2=已通过,3=已拒绝)
     */
    @TableField("auditStatus")
    private Integer auditStatus;
    /**
     * 审核人id
     */
    @TableField("auditUserId")
    private Integer auditUserId;
    /**
     * 审核备注
     */
    @TableField("auditRemark")
    private String auditRemark;
    /**
     * 状态(1=未开始,2=已开始,3=已结束,4=已取消)
     */
    @TableField("status")
    private Integer status;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    @TableField("state")
    private Integer state;
    /**
     * 添加时间
     */
    @TableField("insertTime")
    private Date insertTime;
}
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/AppUserClient.java
New file
@@ -0,0 +1,22 @@
package com.dsh.activity.feginClient.account;
import com.dsh.activity.feginClient.account.model.AppUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
/**
 * @author zhibing.pu
 * @date 2023/6/24 14:50
 */
@FeignClient("mb-cloud-account")
public interface AppUserClient {
    /**
     * 根据用户id获取用户信息
     * @param appUserId
     * @return
     */
    @PostMapping("/base/appUser/queryAppUser")
    AppUser queryAppUser(Integer appUserId);
}
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/StudentClient.java
New file
@@ -0,0 +1,24 @@
package com.dsh.activity.feginClient.account;
import com.dsh.activity.feginClient.account.model.Student;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 15:02
 */
@FeignClient("mb-cloud-account")
public interface StudentClient {
    /**
     * 获取用户学员列表
     * @param appUserId
     * @return
     */
    @PostMapping("/student/queryStudentList")
    List<Student> queryStudentList(Integer appUserId);
}
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/model/AppUser.java
New file
@@ -0,0 +1,114 @@
package com.dsh.activity.feginClient.account.model;
import lombok.Data;
import java.util.Date;
/**
 * @author zhibing.pu
 * @date 2023/6/24 14:51
 */
@Data
public class AppUser {
    private Integer id;
    /**
     * 编号
     */
    private String code;
    /**
     * 姓名
     */
    private String name;
    /**
     * 电话
     */
    private String phone;
    /**
     * 密码
     */
    private String password;
    /**
     * 生日
     */
    private Date birthday;
    /**
     * 性别(1=男,2=女)
     */
    private Integer gender;
    /**
     * 身高
     */
    private Double height;
    /**
     * 体重
     */
    private Double weight;
    /**
     * bmi健康值
     */
    private Double bmi;
    /**
     * 身份证号
     */
    private String idCard;
    /**
     * 微信openid
     */
    private String openid;
    /**
     * 省
     */
    private String province;
    /**
     * 省编号
     */
    private String provinceCode;
    /**
     * 市
     */
    private String city;
    /**
     * 市编号
     */
    private String cityCode;
    /**
     * 是否是年度会员(0=否,1=是)
     */
    private Integer isVip;
    /**
     * 会员有效期
     */
    private Date vipEndTime;
    /**
     * 会员等级id
     */
    private Integer viplevelId;
    /**
     * 推荐用户id
     */
    private Integer referralUserId;
    /**
     * 销售员id
     */
    private Integer salesmanUserId;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    private Integer state;
    /**
     * 剩余积分
     */
    private Integer integral;
    /**
     * 玩湃币
     */
    private Integer playPaiCoins;
    /**
     * 用户头像
     */
    private String headImg;
    /**
     * 添加时间
     */
    private Date insertTime;
}
cloud-server-activity/src/main/java/com/dsh/activity/feginClient/account/model/Student.java
New file
@@ -0,0 +1,70 @@
package com.dsh.activity.feginClient.account.model;
import lombok.Data;
import java.util.Date;
/**
 * @author zhibing.pu
 * @date 2023/6/24 15:02
 */
@Data
public class Student {
    private Integer id;
    /**
     * 用户id
     */
    private Integer appUserId;
    /**
     * 学员姓名
     */
    private String name;
    /**
     * 学员电话
     */
    private String phone;
    /**
     * 生日
     */
    private Date birthday;
    /**
     * 性别(1=男,2=女)
     */
    private Integer sex;
    /**
     * 身高
     */
    private Double height;
    /**
     * 体重
     */
    private Double weight;
    /**
     * bmi健康值
     */
    private Double bmi;
    /**
     * 身份证号
     */
    private String idCard;
    /**
     * 体侧表
     */
    private String lateralSurface;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    private Integer state;
    /**
     * 添加时间
     */
    private Date insertTime;
    /**
     * 头像
     */
    private String headImg;
    /**
     * 是否默认 1默认 2不是默认
     */
    private Integer isDefault;
}
cloud-server-activity/src/main/java/com/dsh/activity/mapper/CouponMapper.java
New file
@@ -0,0 +1,11 @@
package com.dsh.activity.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsh.activity.entity.Coupon;
/**
 * @author zhibing.pu
 * @date 2023/6/24 11:22
 */
public interface CouponMapper extends BaseMapper<Coupon> {
}
cloud-server-activity/src/main/java/com/dsh/activity/model/CouponListVo.java
New file
@@ -0,0 +1,26 @@
package com.dsh.activity.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/24 11:33
 */
@Data
@ApiModel
public class CouponListVo {
    @ApiModelProperty("优惠券id")
    private Integer id;
    @ApiModelProperty("优惠券名称")
    private String name;
    @ApiModelProperty("优惠券类型(1=满减券,2=代金券,3=体验券)")
    private Integer type;
    @ApiModelProperty("使用条件")
    private String useCondition;
    @ApiModelProperty("优惠内容")
    private String favorable;
    @ApiModelProperty("有效时间")
    private String effectiveTime;
}
cloud-server-activity/src/main/java/com/dsh/activity/service/ICouponService.java
New file
@@ -0,0 +1,23 @@
package com.dsh.activity.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsh.activity.entity.Coupon;
import com.dsh.activity.model.CouponListVo;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 11:26
 */
public interface ICouponService extends IService<Coupon>{
    /**
     * 获取购买会员支付成功页面的优惠券
     * @param uid
     * @return
     * @throws Exception
     */
    List<CouponListVo> queryCouponList(Integer uid, Integer distributionMethod) throws Exception;
}
cloud-server-activity/src/main/java/com/dsh/activity/service/impl/CouponServiceImpl.java
New file
@@ -0,0 +1,92 @@
package com.dsh.activity.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.activity.entity.Coupon;
import com.dsh.activity.feginClient.account.AppUserClient;
import com.dsh.activity.feginClient.account.StudentClient;
import com.dsh.activity.feginClient.account.model.AppUser;
import com.dsh.activity.feginClient.account.model.Student;
import com.dsh.activity.mapper.CouponMapper;
import com.dsh.activity.model.CouponListVo;
import com.dsh.activity.service.ICouponService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 11:26
 */
@Service
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {
    @Resource
    private AppUserClient appUserClient;
    @Resource
    private StudentClient studentClient;
    /**
     * 获取购买会员支付成功页面的优惠券
     * @param uid
     * @return
     * @throws Exception
     */
    @Override
    public List<CouponListVo> queryCouponList(Integer uid, Integer distributionMethod) throws Exception {
        AppUser appUser = appUserClient.queryAppUser(uid);
        List<CouponListVo> listVos = new ArrayList<>();
        if(null != appUser){
            List<Integer> userPopulation = new ArrayList<>();
            userPopulation.add(1);//全部用户
            if(1 == appUser.getIsVip()){
                userPopulation.add(2);//年度会员
            }
            List<Student> students = studentClient.queryStudentList(uid);
            if(students.size() > 0){
                userPopulation.add(3);//已有学员用户
            }
            List<Coupon> list = this.list(new QueryWrapper<Coupon>().eq("distributionMethod", distributionMethod).in("userPopulation", userPopulation)
                    .eq("auditStatus", 2).eq("status", 2).eq("state", 1)
                    .last(" and now() between startTime and endTime").orderByDesc("insertTime"));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            for (Coupon coupon : list) {
                CouponListVo couponListVo = new CouponListVo();
                couponListVo.setId(coupon.getId());
                couponListVo.setName(coupon.getName());
                couponListVo.setType(coupon.getType());
                couponListVo.setEffectiveTime(sdf.format(coupon.getStartTime()) + "-" + sdf.format(coupon.getEndTime()));
                String content = coupon.getContent();
                if(coupon.getType() == 1){//满减{"num1":1,"num2":1}
                    JSONObject jsonObject = JSON.parseObject(content);
                    couponListVo.setUseCondition("满" + jsonObject.getDouble("num1") + "元可用");
                    couponListVo.setFavorable(jsonObject.getDouble("num2") + "元");
                }
                if(coupon.getType() == 2){//满减{"num1":1}
                    JSONObject jsonObject = JSON.parseObject(content);
                    couponListVo.setUseCondition("");
                    couponListVo.setFavorable(jsonObject.getDouble("num1") + "元");
                }
                if(coupon.getType() == 3){//体验券{"num1":1}
                    JSONObject jsonObject = JSON.parseObject(content);
                    couponListVo.setUseCondition("");
                    couponListVo.setFavorable(jsonObject.getString("num1"));
                }
                listVos.add(couponListVo);
            }
        }
        return listVos;
    }
}
cloud-server-activity/src/main/java/com/dsh/activity/util/ResultUtil.java
@@ -3,7 +3,6 @@
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
/**
 * 定义统一返回对象
@@ -107,8 +106,8 @@
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", new JSONObject());
    public static  ResultUtil paranErr(String ages){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "【" + ages + "】参数异常", new JSONObject());
    }
    /**
@@ -116,11 +115,10 @@
     * @return
     */
    public static <T> ResultUtil<T> paranErr(T data){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "SYSTEM_RUN_ERROR", data);
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", data);
    }
    @Autowired
    private static MessageUtils messageUtils;
    /**
     * 运行异常
     * @return
cloud-server-activity/src/main/java/com/dsh/activity/util/TokenUtil.java
@@ -2,6 +2,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@@ -12,7 +14,9 @@
    private RedisUtil redisUtil;
    public Integer getUserIdFormRedis(HttpServletRequest request) throws Exception {
    public Integer getUserIdFormRedis() throws Exception {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String requestHeader = request.getHeader("Authorization");
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            requestHeader = requestHeader.substring(requestHeader.indexOf(" ") + 1);
cloud-server-activity/src/main/resources/mapper/CouponMapper.tld
New file
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dsh.activity.mapper.CouponMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.dsh.activity.entity.Coupon">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="type" property="type" />
        <result column="content" property="content" />
        <result column="illustrate" property="illustrate" />
        <result column="distributionMethod" property="distributionMethod" />
        <result column="redemptionMethod" property="redemptionMethod" />
        <result column="cash" property="cash" />
        <result column="integral" property="integral" />
        <result column="userPopulation" property="userPopulation" />
        <result column="quantityIssued" property="quantityIssued" />
        <result column="pickUpQuantity" property="pickUpQuantity" />
        <result column="startTime" property="startTime" />
        <result column="endTime" property="endTime" />
        <result column="useScope" property="useScope" />
        <result column="province" property="province" />
        <result column="provinceCode" property="provinceCode" />
        <result column="city" property="city" />
        <result column="cityCode" property="cityCode" />
        <result column="auditStatus" property="auditStatus" />
        <result column="auditUserId" property="auditUserId" />
        <result column="auditRemark" property="auditRemark" />
        <result column="status" property="status" />
        <result column="state" property="state" />
        <result column="insertTime" property="insertTime" />
    </resultMap>
</mapper>
cloud-server-competition/src/main/java/com/dsh/competition/util/ResultUtil.java
@@ -3,7 +3,6 @@
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
/**
 * 定义统一返回对象
@@ -107,8 +106,8 @@
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", new JSONObject());
    public static  ResultUtil paranErr(String ages){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "【" + ages + "】参数异常", new JSONObject());
    }
    /**
@@ -116,11 +115,10 @@
     * @return
     */
    public static <T> ResultUtil<T> paranErr(T data){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "SYSTEM_RUN_ERROR", data);
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", data);
    }
    @Autowired
    private static MessageUtils messageUtils;
    /**
     * 运行异常
     * @return
cloud-server-competition/src/main/java/com/dsh/competition/util/TokenUtil.java
@@ -2,6 +2,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@@ -12,7 +14,9 @@
    private RedisUtil redisUtil;
    public Integer getUserIdFormRedis(HttpServletRequest request) throws Exception {
    public Integer getUserIdFormRedis() throws Exception {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String requestHeader = request.getHeader("Authorization");
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            requestHeader = requestHeader.substring(requestHeader.indexOf(" ") + 1);
cloud-server-course/pom.xml
@@ -95,6 +95,25 @@
            <artifactId>swagger-models</artifactId>
            <version>1.5.22</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.gavaghan</groupId>
            <artifactId>geodesy</artifactId>
            <version>1.1.3</version>
        </dependency>
    </dependencies>
    <build>
cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java
@@ -3,16 +3,25 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dsh.course.entity.TCourse;
import com.dsh.course.entity.TCoursePackageType;
import com.dsh.course.feignclient.model.ExerciseVideo;
import com.dsh.course.model.BaseVo;
import com.dsh.course.model.CoursePackageList;
import com.dsh.course.model.CoursePackageListVo;
import com.dsh.course.service.TCoursePackageService;
import com.dsh.course.service.TCoursePackageTypeService;
import com.dsh.course.service.TCourseService;
import com.dsh.course.util.ResultUtil;
import com.dsh.course.util.TokenUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@@ -27,6 +36,19 @@
    @Autowired
    private TCourseService courseService;
    @Autowired
    private TCoursePackageService coursePackageService;
    @Autowired
    private TokenUtil tokenUtil;
    @Autowired
    private TCoursePackageTypeService coursePackageTypeService;
    @PostMapping("/course/queryList")
@@ -47,4 +69,54 @@
        return videos;
    }
    @ResponseBody
    @PostMapping("/api/course/queryCoursePackageType")
    @ApiOperation(value = "获取课程类型列表", tags = {"APP-加入玩湃"})
    @ApiImplicitParams({
    })
    public ResultUtil<List<BaseVo>> queryCoursePackageType(){
        try {
            List<TCoursePackageType> coursePackageTypes = coursePackageTypeService.list(new QueryWrapper<TCoursePackageType>().eq("state", 1));
            List<BaseVo> list = new ArrayList<>();
            coursePackageTypes.forEach(c -> {
                BaseVo baseVo = new BaseVo();
                BeanUtils.copyProperties(c, baseVo);
                list.add(baseVo);
            });
            return ResultUtil.success(list);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    @ResponseBody
    @PostMapping("/api/course/queryCourseList")
    @ApiOperation(value = "获取课程列表", tags = {"APP-加入玩湃"})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil<List<CoursePackageListVo>> queryCourseList(@RequestBody CoursePackageList coursePackageList){
        try {
            Integer uid = tokenUtil.getUserIdFormRedis();
            if(null == uid){
                return ResultUtil.tokenErr();
            }
            List<CoursePackageListVo> coursePackageListVos = coursePackageService.queryCourseList(uid, coursePackageList);
            return ResultUtil.success(coursePackageListVos);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
}
cloud-server-course/src/main/java/com/dsh/course/entity/CoursePackagePaymentConfig.java
New file
@@ -0,0 +1,46 @@
package com.dsh.course.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/29 10:42
 */
@Data
@TableName("t_course_package_payment_config")
public class CoursePackagePaymentConfig {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 课包id
     */
    @TableField("coursePackageId")
    private Integer coursePackageId;
    /**
     * 支付方式(1=现金,2=玩湃币)
     */
    @TableField("payType")
    private Integer payType;
    /**
     * 课时数
     */
    @TableField("classHours")
    private Integer classHours;
    /**
     * 现金支付价格
     */
    @TableField("cashPayment")
    private Double cashPayment;
    /**
     * 玩湃币价格
     */
    @TableField("playPaiCoin")
    private Integer playPaiCoin;
}
cloud-server-course/src/main/java/com/dsh/course/feignclient/account/AppUserClient.java
New file
@@ -0,0 +1,21 @@
package com.dsh.course.feignclient.account;
import com.dsh.course.feignclient.account.model.AppUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
/**
 * @author zhibing.pu
 * @date 2023/6/29 14:09
 */
@FeignClient("mb-cloud-account")
public interface AppUserClient {
    /**
     * 根据用户id获取用户信息
     * @param appUserId
     * @return
     */
    @PostMapping("/base/appUser/queryAppUser")
    AppUser queryAppUser(Integer appUserId);
}
cloud-server-course/src/main/java/com/dsh/course/feignclient/account/model/AppUser.java
New file
@@ -0,0 +1,114 @@
package com.dsh.course.feignclient.account.model;
import lombok.Data;
import java.util.Date;
/**
 * @author zhibing.pu
 * @date 2023/6/29 14:09
 */
@Data
public class AppUser {
    private Integer id;
    /**
     * 编号
     */
    private String code;
    /**
     * 姓名
     */
    private String name;
    /**
     * 电话
     */
    private String phone;
    /**
     * 密码
     */
    private String password;
    /**
     * 生日
     */
    private Date birthday;
    /**
     * 性别(1=男,2=女)
     */
    private Integer gender;
    /**
     * 身高
     */
    private Double height;
    /**
     * 体重
     */
    private Double weight;
    /**
     * bmi健康值
     */
    private Double bmi;
    /**
     * 身份证号
     */
    private String idCard;
    /**
     * 微信openid
     */
    private String openid;
    /**
     * 省
     */
    private String province;
    /**
     * 省编号
     */
    private String provinceCode;
    /**
     * 市
     */
    private String city;
    /**
     * 市编号
     */
    private String cityCode;
    /**
     * 是否是年度会员(0=否,1=是)
     */
    private Integer isVip;
    /**
     * 会员有效期
     */
    private Date vipEndTime;
    /**
     * 会员等级id
     */
    private Integer viplevelId;
    /**
     * 推荐用户id
     */
    private Integer referralUserId;
    /**
     * 销售员id
     */
    private Integer salesmanUserId;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    private Integer state;
    /**
     * 剩余积分
     */
    private Integer integral;
    /**
     * 玩湃币
     */
    private Integer playPaiCoins;
    /**
     * 用户头像
     */
    private String headImg;
    /**
     * 添加时间
     */
    private Date insertTime;
}
cloud-server-course/src/main/java/com/dsh/course/feignclient/other/StoreClient.java
New file
@@ -0,0 +1,33 @@
package com.dsh.course.feignclient.other;
import com.dsh.course.feignclient.other.model.Store;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/29 10:09
 */
@FeignClient("mb-cloud-other")
public interface StoreClient {
    /**
     * 根据名称模糊搜索门店
     * @param name
     * @return
     */
    @PostMapping("/store/queryStoreListByName")
    List<Store> queryStoreListByName(String name);
    /**
     * 根据门店id获取门店信息
     * @param id
     * @return
     */
    @PostMapping("/store/queryStoreById")
    Store queryStoreById(Integer id);
}
cloud-server-course/src/main/java/com/dsh/course/feignclient/other/model/Store.java
New file
@@ -0,0 +1,94 @@
package com.dsh.course.feignclient.other.model;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author zhibing.pu
 * @date 2023/6/29 10:09
 */
@Data
public class Store {
    private Integer id;
    /**
     * 门店名称
     */
    private String name;
    /**
     * 门店店长id
     */
    private Integer storeStaffId;
    /**
     * 城市管理员id
     */
    private Integer cityManagerId;
    /**
     * 省
     */
    private String province;
    /**
     * 省编号
     */
    private String provinceCode;
    /**
     * 市
     */
    private String city;
    /**
     * 市编号
     */
    private String cityCode;
    /**
     * 联系电话
     */
    private String phone;
    /**
     * 详细地址
     */
    private String address;
    /**
     * 纬度
     */
    private String lat;
    /**
     * 经度
     */
    private String lon;
    /**
     * 营业开始时间
     */
    private String startTime;
    /**
     * 营业结束时间
     */
    private String endTime;
    /**
     * 封面图
     */
    private String coverDrawing;
    /**
     * 实景图
     */
    private String realPicture;
    /**
     * 门店介绍
     */
    private String introduce;
    /**
     * 福利图片
     */
    private String welfarePicture;
    /**
     * 开始上课图片
     */
    private String classPicture;
    /**
     * 评分
     */
    private BigDecimal score;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    private Integer state;
}
cloud-server-course/src/main/java/com/dsh/course/mapper/CoursePackagePaymentConfigMapper.java
New file
@@ -0,0 +1,11 @@
package com.dsh.course.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsh.course.entity.CoursePackagePaymentConfig;
/**
 * @author zhibing.pu
 * @date 2023/6/29 10:44
 */
public interface CoursePackagePaymentConfigMapper extends BaseMapper<CoursePackagePaymentConfig> {
}
cloud-server-course/src/main/java/com/dsh/course/mapper/TCoursePackageMapper.java
@@ -18,4 +18,6 @@
    List<CourseOfStoreVo> queryStoreOfCourse();
}
cloud-server-course/src/main/java/com/dsh/course/mapper/TCoursePackagePaymentMapper.java
@@ -18,4 +18,12 @@
    List<TCoursePackagePayment> queryAllCoursePackage(@Param("stuId") Integer stuId);
    /**
     * 获取课包购买人数
     * @param coursePackageId
     * @return
     */
    Integer queryCountNumber(@Param("coursePackageId") Integer coursePackageId);
}
cloud-server-course/src/main/java/com/dsh/course/model/BaseVo.java
New file
@@ -0,0 +1,18 @@
package com.dsh.course.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/24 16:25
 */
@Data
@ApiModel
public class BaseVo {
    @ApiModelProperty("数据id")
    private Integer id;
    @ApiModelProperty("名称")
    private String name;
}
cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageList.java
New file
@@ -0,0 +1,28 @@
package com.dsh.course.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/24 17:40
 */
@Data
@ApiModel
public class CoursePackageList {
    @ApiModelProperty(value = "经度", dataType = "string", required = true)
    private String lon;
    @ApiModelProperty(value = "纬度", dataType = "string", required = true)
    private String lat;
    @ApiModelProperty(value = "课程类型id", dataType = "int", required = false)
    private Integer coursePackageTypeId;
    @ApiModelProperty(value = "门店id", dataType = "int", required = false)
    private Integer storeId;
    @ApiModelProperty(value = "搜索内容", dataType = "string", required = false)
    private String search;
    @ApiModelProperty(value = "销量排序(asc=正序,desc=降序)", dataType = "string", required = false)
    private String salesRanking;
    @ApiModelProperty(value = "距离排序(asc=正序,desc=降序)", dataType = "string", required = false)
    private String distanceSort;
}
cloud-server-course/src/main/java/com/dsh/course/model/CoursePackageListVo.java
New file
@@ -0,0 +1,34 @@
package com.dsh.course.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/24 17:34
 */
@Data
@ApiModel
public class CoursePackageListVo {
    @ApiModelProperty("课程id")
    private Integer id;
    @ApiModelProperty("门店名称")
    private String storeName;
    @ApiModelProperty("课程名称")
    private String name;
    @ApiModelProperty("封面图")
    private String coverDrawing;
    @ApiModelProperty("上课时间")
    private String classStartTime;
    @ApiModelProperty("已报名人数")
    private Integer applicantsNumber;
    @ApiModelProperty("原价")
    private Double originalPrice;
    @ApiModelProperty("会员价")
    private Double vipPrice;
    @ApiModelProperty("支付价")
    private Double paymentPrice;
    @ApiModelProperty("距离")
    private Double distance;
}
cloud-server-course/src/main/java/com/dsh/course/service/ICoursePackagePaymentConfigService.java
New file
@@ -0,0 +1,11 @@
package com.dsh.course.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsh.course.entity.CoursePackagePaymentConfig;
/**
 * @author zhibing.pu
 * @date 2023/6/29 10:45
 */
public interface ICoursePackagePaymentConfigService extends IService<CoursePackagePaymentConfig> {
}
cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackagePaymentService.java
@@ -17,4 +17,11 @@
    List<TCoursePackagePayment> queryAllCoursePackage(Integer stuId);
    /**
     * 获取课程购买人数
     * @param coursePackageId
     * @return
     */
    Integer queryCountNumber(Integer coursePackageId);
}
cloud-server-course/src/main/java/com/dsh/course/service/TCoursePackageService.java
@@ -3,6 +3,8 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsh.course.entity.TCoursePackage;
import com.dsh.course.feignclient.model.CourseOfStoreVo;
import com.dsh.course.model.CoursePackageList;
import com.dsh.course.model.CoursePackageListVo;
import java.util.List;
@@ -18,4 +20,13 @@
    List<CourseOfStoreVo> queryStoreOfCourse();
    /**
     * 获取课程列表
     * @param coursePackageList
     * @return
     * @throws Exception
     */
    List<CoursePackageListVo> queryCourseList(Integer uid, CoursePackageList coursePackageList) throws Exception;
}
cloud-server-course/src/main/java/com/dsh/course/service/impl/CoursePackagePaymentConfigServiceImpl.java
New file
@@ -0,0 +1,15 @@
package com.dsh.course.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.course.entity.CoursePackagePaymentConfig;
import com.dsh.course.mapper.CoursePackagePaymentConfigMapper;
import com.dsh.course.service.ICoursePackagePaymentConfigService;
import org.springframework.stereotype.Service;
/**
 * @author zhibing.pu
 * @date 2023/6/29 10:46
 */
@Service
public class CoursePackagePaymentConfigServiceImpl extends ServiceImpl<CoursePackagePaymentConfigMapper, CoursePackagePaymentConfig> implements ICoursePackagePaymentConfigService {
}
cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackagePaymentServiceImpl.java
@@ -23,4 +23,14 @@
    public List<TCoursePackagePayment> queryAllCoursePackage(Integer stuId) {
        return this.baseMapper.queryAllCoursePackage(stuId);
    }
    /**
     * 获取课包购买人数
     * @param coursePackageId
     * @return
     */
    @Override
    public Integer queryCountNumber(Integer coursePackageId) {
        return this.baseMapper.queryCountNumber(coursePackageId);
    }
}
cloud-server-course/src/main/java/com/dsh/course/service/impl/TCoursePackageServiceImpl.java
@@ -1,13 +1,35 @@
package com.dsh.course.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.course.entity.CoursePackagePaymentConfig;
import com.dsh.course.entity.TCoursePackage;
import com.dsh.course.entity.TCoursePackageDiscount;
import com.dsh.course.feignclient.account.AppUserClient;
import com.dsh.course.feignclient.account.model.AppUser;
import com.dsh.course.feignclient.other.StoreClient;
import com.dsh.course.feignclient.other.model.Store;
import com.dsh.course.mapper.TCoursePackageMapper;
import com.dsh.course.feignclient.model.CourseOfStoreVo;
import com.dsh.course.model.CoursePackageList;
import com.dsh.course.model.CoursePackageListVo;
import com.dsh.course.service.ICoursePackagePaymentConfigService;
import com.dsh.course.service.TCoursePackageDiscountService;
import com.dsh.course.service.TCoursePackagePaymentService;
import com.dsh.course.service.TCoursePackageService;
import com.dsh.course.util.GDMapGeocodingUtil;
import com.dsh.course.util.GeodesyUtil;
import com.dsh.course.util.ToolUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
 * <p>
@@ -20,8 +42,179 @@
@Service
public class TCoursePackageServiceImpl extends ServiceImpl<TCoursePackageMapper, TCoursePackage> implements TCoursePackageService {
    @Resource
    private StoreClient storeClient;
    @Autowired
    private GDMapGeocodingUtil gdMapGeocodingUtil;
    @Autowired
    private TCoursePackagePaymentService coursePackagePaymentService;
    @Autowired
    private ICoursePackagePaymentConfigService coursePackagePaymentConfigService;
    @Autowired
    private TCoursePackageDiscountService coursePackageDiscountService;
    @Resource
    private AppUserClient appUserClient;
    @Override
    public List<CourseOfStoreVo> queryStoreOfCourse() {
        return this.baseMapper.queryStoreOfCourse();
    }
    /**
     * 获取课程列表
     * @param coursePackageList
     * @return
     * @throws Exception
     */
    @Override
    public List<CoursePackageListVo> queryCourseList(Integer uid, CoursePackageList coursePackageList) throws Exception {
        AppUser appUser = appUserClient.queryAppUser(uid);
        Map<String, String> geocode = gdMapGeocodingUtil.geocode(coursePackageList.getLon(), coursePackageList.getLat());
        String provinceCode = geocode.get("provinceCode");
        String cityCode = geocode.get("cityCode");
        QueryWrapper<TCoursePackage> wrapper = new QueryWrapper<TCoursePackage>().in("status", Arrays.asList(1, 2))
                .eq("auditStatus", 2).eq("state", 1).eq("provinceCode", provinceCode).eq("cityCode", cityCode);
        if(null != coursePackageList.getCoursePackageTypeId()){
            wrapper.eq("coursePackageTypeId", coursePackageList.getCoursePackageTypeId());
        }
        if(null != coursePackageList.getStoreId()){
            wrapper.eq("storeId", coursePackageList.getStoreId());
        }
        if(null != coursePackageList.getStoreId()){
            wrapper.eq("storeId", coursePackageList.getStoreId());
        }
        if(ToolUtil.isNotEmpty(coursePackageList.getSearch())){
            wrapper.like("name", coursePackageList.getSearch());
            List<Store> stores = storeClient.queryStoreListByName(coursePackageList.getSearch());
            List<Integer> collect = stores.stream().map(Store::getId).collect(Collectors.toList());
            if(collect.size() > 0){
                wrapper.or().in("id", collect);
            }
        }
        List<TCoursePackage> list = this.list(wrapper.last(" order by sort, insertTime desc"));
        List<CoursePackageListVo> listVos = new ArrayList<>();
        for (TCoursePackage coursePackage : list) {
            Store store = storeClient.queryStoreById(coursePackage.getStoreId());
            Integer integer = coursePackagePaymentService.queryCountNumber(coursePackage.getId());
            CoursePackagePaymentConfig coursePackagePaymentConfig = coursePackagePaymentConfigService.getOne(new QueryWrapper<CoursePackagePaymentConfig>()
                    .eq("coursePackageId", coursePackage.getId()).last(" order by if(payType = 1, cashPayment, playPaiCoin)"));
            CoursePackageListVo coursePackageListVo = new CoursePackageListVo();
            coursePackageListVo.setId(coursePackage.getId());
            coursePackageListVo.setName(coursePackage.getName());
            coursePackageListVo.setStoreName(null != store ? store.getName() : "");
            coursePackageListVo.setCoverDrawing(coursePackage.getCoverDrawing());
            coursePackageListVo.setClassStartTime(coursePackage.getClassStartTime() + "-" + coursePackage.getClassEndTime());
            coursePackageListVo.setApplicantsNumber(integer);
            coursePackageListVo.setOriginalPrice(coursePackagePaymentConfig.getPayType() == 1 ? coursePackagePaymentConfig.getCashPayment() : coursePackagePaymentConfig.getPlayPaiCoin().doubleValue());
            TCoursePackageDiscount coursePackageDiscount = coursePackageDiscountService.getOne(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackageId", coursePackage.getId()).eq("auditStatus", 2).eq("type", 1));
            if(1 == appUser.getIsVip() && null != coursePackageDiscount){
                //{"num1":100}
                JSONObject jsonObject = JSON.parseObject(coursePackageDiscount.getContent());
                coursePackageListVo.setVipPrice(jsonObject.getDouble("num1"));
            }
            coursePackageDiscount = coursePackageDiscountService.getOne(new QueryWrapper<TCoursePackageDiscount>().eq("coursePackageId", coursePackage.getId()).eq("auditStatus", 2).eq("type", 3));
            if(null == coursePackageDiscount){
                coursePackageListVo.setPaymentPrice(coursePackageListVo.getOriginalPrice());
            }else{
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                /**
                 * [{
                 *     "startDate": "2023-01-01 00:00:00",
                 *     "endDate": "2023-12-31 23:59:59",
                 *     "startTime": "02:00:00",
                 *     "endTime": "23:00:00",
                 *     "weeks": [1, 2, 7],
                 *     "cashPayment": 100
                 * }]
                 */
                JSONArray jsonArray = JSON.parseArray(coursePackageDiscount.getContent());
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    String startDate = jsonObject.getString("startDate");
                    String endDate = jsonObject.getString("endDate");
                    String startTime = jsonObject.getString("startTime");
                    String endTime = jsonObject.getString("endTime");
                    List<Integer> weeks = jsonObject.getJSONArray("weeks").toJavaList(Integer.class);
                    Double cashPayment = jsonObject.getDouble("cashPayment");
                    Date startDate_date = sdf.parse(startDate);
                    Date endDate_date = sdf.parse(endDate);
                    long timeMillis = System.currentTimeMillis();
                    if(timeMillis >= startDate_date.getTime() && timeMillis < endDate_date.getTime()){
                        Date date = new Date();
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(date);
                        int week = calendar.get(Calendar.DAY_OF_WEEK);
                        boolean isFirstSunday = (calendar.getFirstDayOfWeek() == Calendar.SUNDAY);
                        if(isFirstSunday){
                            week = week - 1;
                            if(week == 0){
                                week = 7;
                            }
                        }
                        if(!weeks.contains(week)){
                            continue;
                        }
                        String[] split = startTime.split(":");
                        Integer hour1 = Integer.valueOf(split[0]);
                        Calendar s = Calendar.getInstance();
                        s.setTime(date);
                        s.set(Calendar.HOUR_OF_DAY, hour1);
                        s.set(Calendar.MINUTE, Integer.valueOf(split[1]));
                        s.set(Calendar.SECOND, Integer.valueOf(split[2]));
                        String[] split1 = endTime.split(":");
                        Integer hour2 = Integer.valueOf(split1[0]);
                        Calendar e = Calendar.getInstance();
                        e.setTime(date);
                        e.set(Calendar.HOUR_OF_DAY, hour2);
                        e.set(Calendar.MINUTE, Integer.valueOf(split1[1]));
                        e.set(Calendar.SECOND, Integer.valueOf(split1[2]));
                        if(hour1 > hour2){
                            if(s.getTimeInMillis() > date.getTime()){
                                s.set(Calendar.DAY_OF_YEAR, s.get(Calendar.DAY_OF_YEAR) - 1);
                            }else{
                                e.set(Calendar.DAY_OF_YEAR, e.get(Calendar.DAY_OF_YEAR) + 1);
                            }
                        }
                        if(timeMillis >= s.getTimeInMillis() && timeMillis < e.getTimeInMillis()){
                            coursePackageListVo.setPaymentPrice(cashPayment);
                        }
                    }
                }
            }
            Map<String, Double> distance = GeodesyUtil.getDistance(coursePackageList.getLon() + "," + coursePackageList.getLat(), store.getLon() + "," + store.getLat());
            coursePackageListVo.setDistance(distance.get("WGS84") / 1000);
            listVos.add(coursePackageListVo);
        }
        //销量排行
        if(ToolUtil.isNotEmpty(coursePackageList.getSalesRanking())){
            Collections.sort(listVos, new Comparator<CoursePackageListVo>() {
                public int compare(CoursePackageListVo s1, CoursePackageListVo s2) {
                    return Integer.compare(s1.getApplicantsNumber(), s2.getApplicantsNumber());
                }
            });
        }
        //距离排行
        if(ToolUtil.isNotEmpty(coursePackageList.getDistanceSort())){
            Collections.sort(listVos, new Comparator<CoursePackageListVo>() {
                public int compare(CoursePackageListVo s1, CoursePackageListVo s2) {
                    return Double.compare(s1.getDistance(), s2.getDistance());
                }
            });
        }
        return listVos;
    }
}
cloud-server-course/src/main/java/com/dsh/course/service/impl/TCourseServiceImpl.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 课程 服务实现类
@@ -17,4 +18,6 @@
@Service
public class TCourseServiceImpl extends ServiceImpl<TCourseMapper, TCourse> implements TCourseService {
}
cloud-server-course/src/main/java/com/dsh/course/util/GDMapGeocodingUtil.java
New file
@@ -0,0 +1,148 @@
package com.dsh.course.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dsh.course.util.httpClinet.HttpClientUtil;
import com.dsh.course.util.httpClinet.HttpResult;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 高德地图的地理编码工具类
 */
@Component
public class GDMapGeocodingUtil {
    private String key = "fb131ad2dbfb3f39d7d37d244b92aa2d";
    /**
     * 将行政区域名称转化为坐标
     * @param province
     * @param city
     * @param county
     * @param address
     * @return
     */
    public Map<String, Object> geocoding(String province, String city, String county, String address) throws Exception{
        Map<String, Object> map = new HashMap<>();
        if(ToolUtil.isEmpty(province)){
            map.put("status", -1);
            map.put("data", "省不能为空");
            return map;
        }
        if((ToolUtil.isEmpty(city) && ToolUtil.isNotEmpty(county)) || (ToolUtil.isEmpty(city) && ToolUtil.isNotEmpty(address))){
            map.put("status", -1);
            map.put("data", "市不能为空");
            return map;
        }
        if((ToolUtil.isEmpty(county) && ToolUtil.isNotEmpty(address))){
            map.put("status", -1);
            map.put("data", "县/区不能为空");
            return map;
        }
        String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON";
        url += "&address=" + province + (ToolUtil.isNotEmpty(city) ? city : "") + (ToolUtil.isNotEmpty(county) ? county : "") + (ToolUtil.isNotEmpty(address) ? address : "");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        String status = jsonObject.getString("status");
        List<String> list = new ArrayList<>();
        if(status.equals("1")){
            JSONArray geocodes = jsonObject.getJSONArray("geocodes");
            for(int i = 0; i < geocodes.size(); i++){
                String location = geocodes.getJSONObject(i).getString("location");
                list.add(location);
            }
        }
        map.put("status", 0);
        map.put("data", list);
        return map;
    }
    public Map<String, Object> geocoding(String address) throws Exception{
        Map<String, Object> map = new HashMap<>();
        String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON&address=" + address;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        String status = jsonObject.getString("status");
        List<String> list = new ArrayList<>();
        if(status.equals("1")){
            JSONArray geocodes = jsonObject.getJSONArray("geocodes");
            for(int i = 0; i < geocodes.size(); i++){
                String location = geocodes.getJSONObject(i).getString("location");
                list.add(location);
            }
        }
        map.put("status", 0);
        map.put("data", list);
        return map;
    }
    /**
     * 根据经纬度获取行政区域信息
     * @param lon
     * @param lan
     * @return
     * @throws Exception
     */
    public Map<String, String> geocode(String lon, String lan) throws Exception{
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + key + "&location=" + lon + "," + lan;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        Map<String, String> map = new HashMap<>();
        if(jsonObject.getString("status").equals("1")){
            JSONObject regeocode = jsonObject.getJSONObject("regeocode");
            JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
            String address = regeocode.getString("formatted_address");
            map.put("address", address);
            String code = addressComponent.getString("adcode");
            String province = addressComponent.getString("province");
            String city = addressComponent.getString("city");
            String district = addressComponent.getString("district");
            map.put("province", province);
            map.put("provinceCode", code.substring(0, 2) + "0000");
            map.put("city", city);
            map.put("cityCode", code.substring(0, 4) + "00");
            map.put("district", district);
            map.put("districtCode", code);
        }
        return map;
    }
    /**
     * 坐标转换
     * @param locations 经度和纬度用","分割,经度在前,纬度在后,经纬度小数点后不得超过6位。多个坐标对之间用”|”进行分隔最多支持40对坐标。
     * @param coordsys  可选值:gps;mapbar;baidu;autonavi(不进行转换)
     * @return
     * @throws Exception
     */
    public Map<String, String> convert(String locations, String coordsys) throws Exception{
        String url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + locations + "&coordsys=" + coordsys + "&output=json&key=" + key;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        Map<String, String> map = new HashMap<>();
        if("1".equals(jsonObject.getString("status"))){
            map.put("code", jsonObject.getString("infocode"));//"10000"
            map.put("info", jsonObject.getString("info"));//status为0时,info返回错误原;否则返回“OK”。
            map.put("locations", jsonObject.getString("locations").split(";")[0]);//转换之后的坐标。若有多个坐标,则用 “;”进行区分和间隔
        }else{
            map.put("code", jsonObject.getString("infocode"));
            map.put("info", jsonObject.getString("info"));//status为0时,info返回错误原;否则返回“OK”。
        }
        return map;
    }
}
cloud-server-course/src/main/java/com/dsh/course/util/GeodesyUtil.java
New file
@@ -0,0 +1,63 @@
package com.dsh.course.util;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import java.util.HashMap;
import java.util.Map;
/**
 * 计算两个金纬度坐标之间的直线距离
 */
public class GeodesyUtil {
    /**
     * 获取直线距离
     * @param fromLonLat
     * @param toLonLat
     * @return
     */
    public static Map<String, Double> getDistance(String fromLonLat, String toLonLat){
        String[] from = fromLonLat.split(",");
        String[] to = toLonLat.split(",");
        GlobalCoordinates source = new GlobalCoordinates(Double.valueOf(from[1]), Double.valueOf(from[0]));
        GlobalCoordinates target = new GlobalCoordinates(Double.valueOf(to[1]), Double.valueOf(to[0]));
        double Sphere = getDistanceMeter(source, target, Ellipsoid.Sphere);
        double WGS84 = getDistanceMeter(source, target, Ellipsoid.WGS84);
        double GRS80 = getDistanceMeter(source, target, Ellipsoid.GRS80);
        double GRS67 = getDistanceMeter(source, target, Ellipsoid.GRS67);
        double ANS = getDistanceMeter(source, target, Ellipsoid.ANS);
        double WGS72 = getDistanceMeter(source, target, Ellipsoid.WGS72);
        double Clarke1858 = getDistanceMeter(source, target, Ellipsoid.Clarke1858);
        double Clarke1880 = getDistanceMeter(source, target, Ellipsoid.Clarke1880);
//        System.out.println("Sphere坐标系计算结果:"+Sphere + "米");
//        System.out.println("WGS84坐标系计算结果:"+WGS84 + "米");
//        System.out.println("GRS80坐标系计算结果:"+GRS80 + "米");
//        System.out.println("GRS67坐标系计算结果:"+GRS67 + "米");
//        System.out.println("ANS坐标系计算结果:"+ANS + "米");
//        System.out.println("WGS72坐标系计算结果:"+WGS72 + "米");
//        System.out.println("Clarke1858坐标系计算结果:"+Clarke1858 + "米");
//        System.out.println("Clarke1880坐标系计算结果:"+Clarke1880 + "米");
        Map<String, Double> map = new HashMap<>();
        map.put("Sphere", Sphere);
        map.put("WGS84", WGS84);
        map.put("GRS80", GRS80);
        map.put("GRS67", GRS67);
        map.put("ANS", ANS);
        map.put("WGS72", WGS72);
        map.put("Clarke1858", Clarke1858);
        map.put("Clarke1880", Clarke1880);
        return map;
    }
    private static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid){
        //创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);
        return geoCurve.getEllipsoidalDistance();
    }
}
cloud-server-course/src/main/java/com/dsh/course/util/ResultUtil.java
@@ -3,7 +3,6 @@
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
/**
 * 定义统一返回对象
@@ -107,8 +106,8 @@
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", new JSONObject());
    public static  ResultUtil paranErr(String ages){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "【" + ages + "】参数异常", new JSONObject());
    }
    /**
@@ -116,11 +115,10 @@
     * @return
     */
    public static <T> ResultUtil<T> paranErr(T data){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "SYSTEM_RUN_ERROR", data);
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", data);
    }
    @Autowired
    private static MessageUtils messageUtils;
    /**
     * 运行异常
     * @return
cloud-server-course/src/main/java/com/dsh/course/util/TokenUtil.java
@@ -2,6 +2,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@@ -12,7 +14,9 @@
    private RedisUtil redisUtil;
    public Integer getUserIdFormRedis(HttpServletRequest request) throws Exception {
    public Integer getUserIdFormRedis() throws Exception {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String requestHeader = request.getHeader("Authorization");
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            requestHeader = requestHeader.substring(requestHeader.indexOf(" ") + 1);
cloud-server-course/src/main/java/com/dsh/course/util/httpClinet/HttpClientUtil.java
New file
@@ -0,0 +1,267 @@
package com.dsh.course.util.httpClinet;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * http工具类
 */
public class HttpClientUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    private static PoolingHttpClientConnectionManager connectionManager;
    {
        //1.创建连接池管理器
        connectionManager = new PoolingHttpClientConnectionManager(60000,
                TimeUnit.MILLISECONDS);
        connectionManager.setMaxTotal(1000);
        connectionManager.setDefaultMaxPerRoute(50);
    }
    /**
     * 创建一个httpClient对象
     */
    private static CloseableHttpClient getHttpCline(){
        return  HttpClients.custom()
                .setConnectionManager(connectionManager)
                .disableAutomaticRetries()
                .build();
    }
    private static RequestConfig getRequestConfig(){
        RequestConfig.Builder builder = RequestConfig.custom();
        builder.setSocketTimeout(60000)//3.1设置客户端等待服务端返回数据的超时时间
                .setConnectTimeout(30000)//3.2设置客户端发起TCP连接请求的超时时间
                .setExpectContinueEnabled(true)
                .setConnectionRequestTimeout(30000);//3.3设置客户端从连接池获取链接的超时时间
        return builder.build();
    }
    /**
     * 创建一个POST请求实例
     * @param url       请求地址
     * @param params    请求参数
     */
    private static CloseableHttpResponse setPostHttpRequset(String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        if(null != header){
            for(String key : header.keySet()){
                httpPost.setHeader(key, header.get(key));
            }
        }
        List<NameValuePair> list = new ArrayList<>();
        if(null != params){
            Set<String> keys = params.keySet();
            for(String key : keys){
                list.add(new BasicNameValuePair(key, null == params.get(key) ? null : params.get(key).toString()));
            }
        }
        switch (contentType){
            case "form":
                httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
                break;
            case "json":
                ObjectMapper objectMapper = new ObjectMapper();
                String s =objectMapper.writeValueAsString(params);
                httpPost.setEntity(new StringEntity(s, ContentType.create(ContentType.APPLICATION_JSON.getMimeType(), Charset.forName("UTF-8"))));
                break;
        }
        return getHttpCline().execute(httpPost);
    }
    /**
     * 获取get请求实例
     * @param url       请求地址
     * @param params    请求参数
     */
    private static CloseableHttpResponse setGetHttpRequset(String url, Map<String, Object> params, Map<String, String> header) throws Exception{
        StringBuffer sb = new StringBuffer();
        String p = "";
        if(null != params){
            Set<String> keys = params.keySet();
            for(String key : keys){
                sb.append(key + "=" + params.get(key) + "&");
            }
            p = "?" + sb.substring(0, sb.length() - 1);
        }
        HttpGet httpGet = new HttpGet(url + p);
        httpGet.setConfig(getRequestConfig());
        if(null != header){
            for(String key : header.keySet()){
                httpGet.setHeader(key, header.get(key));
            }
        }
        return getHttpCline().execute(httpGet);
    }
    /**
     * 发送http请求
     * @param mothed        "GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS"
     * @param url           请求地址
     * @param params        请求参数
     * @param header        请求头
     * @param contentType   参数请求方式form/json
     * @return
     */
    public static HttpResult pushHttpRequset(String mothed, String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
        String randome = UUID.randomUUID().toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
        logger.info(sdf.format(new Date()) + "----(" + randome + ")请求参数:" + JSON.toJSONString(params));
        CloseableHttpResponse httpResponse = null;
        switch (mothed){
            case "GET":
                httpResponse = setGetHttpRequset(url, params, header);
                break;
            case "POST":
                httpResponse = setPostHttpRequset(url, params, header, contentType);
                break;
        }
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        logger.info(sdf.format(new Date()) + "----(" + randome + ")返回结果:" + content);
        HttpResult httpResult = HttpResult.getHttpResult(statusCode, content);
        close(httpResponse);
        return httpResult;
    }
    /**
     * 发送XML请求
     * @param url       请求地址
     * @param xml       XML数据
     * @param header    自定义请求头
     * @return
     */
    public static HttpResult pushHttpRequsetXml(String url, String xml, Map<String, String> header) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        for(String key : header.keySet()){
            httpPost.setHeader(key, header.get(key));
        }
        httpPost.setHeader("Content-Type", "application/xml");
        httpPost.setEntity(new StringEntity(xml, "UTF-8"));
        CloseableHttpResponse httpResponse = getHttpCline().execute(httpPost);
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        HttpResult httpResult = HttpResult.getHttpResult(statusCode, content);
        close(httpResponse);
        return httpResult;
    }
    /**
     * 请求https发送XML请求
     * @param url           接口路径
     * @param xml           内容
     * @param header        请求头
     * @param certPassword      证书密码
     * @param certPath      证书路径
     * @param certType      证书类型
     * @return
     * @throws Exception
     */
    public String pushHttpsRequsetXml(String url, String xml, Map<String, String> header, String certPassword, String certPath, String certType) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        for(String key : header.keySet()){
            httpPost.setHeader(key, header.get(key));
        }
        httpPost.setHeader("Content-Type", "application/xml");
        httpPost.setEntity(new StringEntity(xml, "UTF-8"));
        CloseableHttpClient httpCline = this.initCert(certPassword, certPath, certType);
        CloseableHttpResponse httpResponse = httpCline.execute(httpPost);
        String content = null;
        if(httpResponse.getStatusLine().getStatusCode() == 200){
            content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        }else{
            content = "返回状态码:" + httpResponse.getStatusLine() + "。" + EntityUtils.toString(httpResponse.getEntity());
        }
        this.close(httpResponse);
        httpCline.close();
        return content;
    }
    /**
     * 初始化https对象(带证书)
     * @param key       证书密码
     * @param certPath  证书路径
     * @param certType  证书类型
     * @throws Exception
     */
    private CloseableHttpClient initCert(String key, String certPath, String certType) throws Exception {
        KeyStore keyStore = KeyStore.getInstance(certType);
        InputStream inputStream = new FileInputStream(new File(certPath));
        try {
            keyStore.load(inputStream, key.toCharArray());
        } finally {
            inputStream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();
        SSLConnectionSocketFactory sslsf =
                new SSLConnectionSocketFactory(sslcontext, new String[] {"TLSv1"}, null,
                        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }
    /**
     * 关闭资源
     */
    private static void close(CloseableHttpResponse httpResponse){
        try {
            if(null != httpResponse){
                EntityUtils.consume(httpResponse.getEntity());//此处高能,通过源码分析,由EntityUtils是否回收HttpEntity
                httpResponse.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if(null != httpResponse){
                    httpResponse.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
cloud-server-course/src/main/java/com/dsh/course/util/httpClinet/HttpResult.java
New file
@@ -0,0 +1,31 @@
package com.dsh.course.util.httpClinet;
import lombok.Data;
/**
 * http请求返回封装
 */
@Data
public class HttpResult {
    /**
     * 返回状态码
     */
    private Integer code;
    /**
     * 返回结果
     */
    private String data;
    /**
     * 返回封装结果
     * @param code
     * @param data
     * @return
     */
    public static HttpResult getHttpResult(Integer code, String data){
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(code);
        httpResult.setData(data);
        return httpResult;
    }
}
cloud-server-course/src/main/resources/mapper/CoursePackagePaymentConfigMapper.xml
New file
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dsh.course.mapper.CoursePackagePaymentConfigMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.dsh.course.entity.CoursePackagePaymentConfig">
        <id column="id" property="id" />
        <result column="coursePackageId" property="coursePackageId" />
        <result column="payType" property="payType" />
        <result column="classHours" property="classHours" />
        <result column="cashPayment" property="cashPayment" />
        <result column="playPaiCoin" property="playPaiCoin" />
    </resultMap>
</mapper>
cloud-server-course/src/main/resources/mapper/TCourseMapper.xml
@@ -15,4 +15,5 @@
        <result column="insertTime" property="insertTime" />
    </resultMap>
</mapper>
cloud-server-course/src/main/resources/mapper/TCoursePackagePaymentMapper.xml
@@ -46,4 +46,12 @@
        WHERE user_id = #{stuId}
    </select>
    <select id="queryCountNumber" resultType="int">
        SELECT
        count( 1 ) AS num
        FROM (
          SELECT appUserId FROM t_course_package_payment WHERE payStatus = 2 AND state = 1 and coursePackageId = #{coursePackageId} GROUP BY appUserId
        ) AS aa
    </select>
</mapper>
cloud-server-other/pom.xml
@@ -91,6 +91,20 @@
            <version>2.3.30</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.2</version>
        </dependency>
    </dependencies>
cloud-server-other/src/main/java/com/dsh/other/controller/StoreConfigController.java
New file
@@ -0,0 +1,57 @@
package com.dsh.other.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dsh.other.entity.StoreConfig;
import com.dsh.other.model.StoreConfigVo;
import com.dsh.other.service.StoreConfigService;
import com.dsh.other.util.ResultUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 16:11
 */
@RestController
@RequestMapping("")
public class StoreConfigController {
    @Autowired
    private StoreConfigService storeConfigService;
    @ResponseBody
    @PostMapping("/base/store/queryStoreConfig")
    @ApiOperation(value = "获取门店模块配置", tags = {"APP-加入玩湃"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "门店id", name = "storeId", dataType = "int", required = true),
    })
    public ResultUtil<List<StoreConfigVo>> queryStoreConfig(@RequestBody Integer storeId){
        if(null == storeId){
            return ResultUtil.paranErr("storeId");
        }
        try {
            List<StoreConfig> list = storeConfigService.list(new QueryWrapper<StoreConfig>().eq("storeId", storeId).orderByAsc("sort"));
            List<StoreConfigVo> listVo = new ArrayList<>();
            for (StoreConfig storeConfig : list) {
                StoreConfigVo storeConfigVo = new StoreConfigVo();
                BeanUtils.copyProperties(storeConfig, storeConfigVo);
                listVo.add(storeConfigVo);
            }
            return ResultUtil.success(listVo);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
}
cloud-server-other/src/main/java/com/dsh/other/controller/StoreController.java
New file
@@ -0,0 +1,108 @@
package com.dsh.other.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dsh.other.entity.Store;
import com.dsh.other.model.BaseVo;
import com.dsh.other.service.StoreService;
import com.dsh.other.util.ResultUtil;
import com.dsh.other.util.ToolUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhibing.pu
 * @date 2023/6/24 15:42
 */
@RestController
@RequestMapping("")
public class StoreController {
    @Autowired
    private StoreService storeService;
    /**
     * 获取门店列表
     * @param provinceCode
     * @param cityCode
     * @return
     */
    @ResponseBody
    @PostMapping("/store/queryStoreList")
    public List<Store> queryStoreList(@RequestBody String provinceCode, @RequestBody String cityCode){
        try {
            return storeService.queryStorsList(provinceCode, cityCode);
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }
    @ResponseBody
    @PostMapping("/base/store/queryStoreLists")
    @ApiOperation(value = "获取门店列表", tags = {"APP-加入玩湃"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "经纬", name = "lon", dataType = "string", required = true),
            @ApiImplicitParam(value = "纬度", name = "lat", dataType = "string", required = true),
    })
    public ResultUtil<List<BaseVo>> queryStoreLists(@RequestBody String lon, @RequestBody String lat){
        if(ToolUtil.isEmpty(lon)){
            return ResultUtil.paranErr("lon");
        }
        if(ToolUtil.isEmpty(lat)){
            return ResultUtil.paranErr("lat");
        }
        try {
            List<BaseVo> baseVos = storeService.queryStoreLists(lon, lat);
            return ResultUtil.success(baseVos);
        }catch (Exception e){
            e.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 根据门店模糊搜索店铺
     * @param name
     * @return
     */
    @ResponseBody
    @PostMapping("/store/queryStoreListByName")
    public List<Store> queryStoreListByName(@RequestBody String name){
        try {
            List<Store> stores = storeService.list(new QueryWrapper<Store>().eq("state", 1).like("name", name));
            return stores;
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }
    /**
     * 根据门店
     * @param id
     * @return
     */
    @ResponseBody
    @PostMapping("/store/queryStoreById")
    public Store queryStoreById(@RequestBody Integer id){
        try {
            return storeService.getById(id);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}
cloud-server-other/src/main/java/com/dsh/other/model/BaseVo.java
New file
@@ -0,0 +1,18 @@
package com.dsh.other.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/24 16:25
 */
@Data
@ApiModel
public class BaseVo {
    @ApiModelProperty("数据id")
    private Integer id;
    @ApiModelProperty("名称")
    private String name;
}
cloud-server-other/src/main/java/com/dsh/other/model/StoreConfigVo.java
New file
@@ -0,0 +1,22 @@
package com.dsh.other.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @date 2023/6/24 16:16
 */
@Data
@ApiModel
public class StoreConfigVo {
    @ApiModelProperty(" 数据类型(1=报名玩湃课程,2=预约场地,3=报名赛事及活动,4=免费福利,5=线上课程积分,6=购买优惠门票,7=看视频得奖励,8=智慧球场)")
    private Integer type;
    @ApiModelProperty("是否开启(0=否,1=是)")
    private Integer isOpen;
    @ApiModelProperty("排序")
    private Integer sort;
    @ApiModelProperty("背景图")
    private String backgroundImage;
}
cloud-server-other/src/main/java/com/dsh/other/service/StoreService.java
@@ -2,6 +2,9 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsh.other.entity.Store;
import com.dsh.other.model.BaseVo;
import java.util.List;
/**
@@ -14,4 +17,24 @@
 */
public interface StoreService extends IService<Store> {
    /**
     * 获取列表数据
     * @param provinceCode
     * @param cityCode
     * @return
     * @throws Exception
     */
    List<Store> queryStorsList(String provinceCode, String cityCode) throws Exception;
    /**
     * 获取门店列表
     * @param lon
     * @param lat
     * @return
     * @throws Exception
     */
    List<BaseVo> queryStoreLists(String lon, String lat) throws Exception;
}
cloud-server-other/src/main/java/com/dsh/other/service/impl/StoreServiceImpl.java
@@ -1,11 +1,21 @@
package com.dsh.other.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.other.entity.Store;
import com.dsh.other.mapper.StoreMapper;
import com.dsh.other.model.BaseVo;
import com.dsh.other.service.StoreService;
import com.dsh.other.util.GDMapGeocodingUtil;
import com.dsh.other.util.ToolUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * <p>
@@ -18,4 +28,52 @@
@Service
public class StoreServiceImpl extends ServiceImpl<StoreMapper,Store> implements StoreService {
    @Autowired
    private GDMapGeocodingUtil gdMapGeocodingUtil;
    /**
     * 获取列表数据
     * @param provinceCode
     * @param cityCode
     * @return
     * @throws Exception
     */
    @Override
    public List<Store> queryStorsList(String provinceCode, String cityCode) throws Exception {
        QueryWrapper objectQueryWrapper = new QueryWrapper<Store>().eq("state", 1);
        if(ToolUtil.isNotEmpty(provinceCode)){
            objectQueryWrapper.eq("provinceCode", provinceCode);
        }
        if(ToolUtil.isNotEmpty(cityCode)){
            objectQueryWrapper.eq("cityCode", cityCode);
        }
        List<Store> list = this.list(objectQueryWrapper);
        return list;
    }
    /**
     * 获取列表数据
     * @param lon
     * @param lat
     * @return
     * @throws Exception
     */
    @Override
    public List<BaseVo> queryStoreLists(String lon, String lat) throws Exception {
        Map<String, String> geocode = gdMapGeocodingUtil.geocode(lon, lat);
        List<BaseVo> list = new ArrayList<>();
        if(null != geocode){
            String provinceCode = geocode.get("provinceCode");
            String cityCode = geocode.get("cityCode");
            List<Store> stores = this.queryStorsList(provinceCode, cityCode);
            for (Store store : stores) {
                BaseVo baseVo = new BaseVo();
                BeanUtils.copyProperties(store, baseVo);
                list.add(baseVo);
            }
        }
        return list;
    }
}
cloud-server-other/src/main/java/com/dsh/other/util/GDMapGeocodingUtil.java
New file
@@ -0,0 +1,148 @@
package com.dsh.other.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dsh.other.util.httpClinet.HttpClientUtil;
import com.dsh.other.util.httpClinet.HttpResult;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 高德地图的地理编码工具类
 */
@Component
public class GDMapGeocodingUtil {
    private String key = "fb131ad2dbfb3f39d7d37d244b92aa2d";
    /**
     * 将行政区域名称转化为坐标
     * @param province
     * @param city
     * @param county
     * @param address
     * @return
     */
    public Map<String, Object> geocoding(String province, String city, String county, String address) throws Exception{
        Map<String, Object> map = new HashMap<>();
        if(ToolUtil.isEmpty(province)){
            map.put("status", -1);
            map.put("data", "省不能为空");
            return map;
        }
        if((ToolUtil.isEmpty(city) && ToolUtil.isNotEmpty(county)) || (ToolUtil.isEmpty(city) && ToolUtil.isNotEmpty(address))){
            map.put("status", -1);
            map.put("data", "市不能为空");
            return map;
        }
        if((ToolUtil.isEmpty(county) && ToolUtil.isNotEmpty(address))){
            map.put("status", -1);
            map.put("data", "县/区不能为空");
            return map;
        }
        String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON";
        url += "&address=" + province + (ToolUtil.isNotEmpty(city) ? city : "") + (ToolUtil.isNotEmpty(county) ? county : "") + (ToolUtil.isNotEmpty(address) ? address : "");
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        String status = jsonObject.getString("status");
        List<String> list = new ArrayList<>();
        if(status.equals("1")){
            JSONArray geocodes = jsonObject.getJSONArray("geocodes");
            for(int i = 0; i < geocodes.size(); i++){
                String location = geocodes.getJSONObject(i).getString("location");
                list.add(location);
            }
        }
        map.put("status", 0);
        map.put("data", list);
        return map;
    }
    public Map<String, Object> geocoding(String address) throws Exception{
        Map<String, Object> map = new HashMap<>();
        String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON&address=" + address;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        String status = jsonObject.getString("status");
        List<String> list = new ArrayList<>();
        if(status.equals("1")){
            JSONArray geocodes = jsonObject.getJSONArray("geocodes");
            for(int i = 0; i < geocodes.size(); i++){
                String location = geocodes.getJSONObject(i).getString("location");
                list.add(location);
            }
        }
        map.put("status", 0);
        map.put("data", list);
        return map;
    }
    /**
     * 根据经纬度获取行政区域信息
     * @param lon
     * @param lan
     * @return
     * @throws Exception
     */
    public Map<String, String> geocode(String lon, String lan) throws Exception{
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + key + "&location=" + lon + "," + lan;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        Map<String, String> map = new HashMap<>();
        if(jsonObject.getString("status").equals("1")){
            JSONObject regeocode = jsonObject.getJSONObject("regeocode");
            JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
            String address = regeocode.getString("formatted_address");
            map.put("address", address);
            String code = addressComponent.getString("adcode");
            String province = addressComponent.getString("province");
            String city = addressComponent.getString("city");
            String district = addressComponent.getString("district");
            map.put("province", province);
            map.put("provinceCode", code.substring(0, 2) + "0000");
            map.put("city", city);
            map.put("cityCode", code.substring(0, 4) + "00");
            map.put("district", district);
            map.put("districtCode", code);
        }
        return map;
    }
    /**
     * 坐标转换
     * @param locations 经度和纬度用","分割,经度在前,纬度在后,经纬度小数点后不得超过6位。多个坐标对之间用”|”进行分隔最多支持40对坐标。
     * @param coordsys  可选值:gps;mapbar;baidu;autonavi(不进行转换)
     * @return
     * @throws Exception
     */
    public Map<String, String> convert(String locations, String coordsys) throws Exception{
        String url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + locations + "&coordsys=" + coordsys + "&output=json&key=" + key;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "json");
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        Map<String, String> map = new HashMap<>();
        if("1".equals(jsonObject.getString("status"))){
            map.put("code", jsonObject.getString("infocode"));//"10000"
            map.put("info", jsonObject.getString("info"));//status为0时,info返回错误原;否则返回“OK”。
            map.put("locations", jsonObject.getString("locations").split(";")[0]);//转换之后的坐标。若有多个坐标,则用 “;”进行区分和间隔
        }else{
            map.put("code", jsonObject.getString("infocode"));
            map.put("info", jsonObject.getString("info"));//status为0时,info返回错误原;否则返回“OK”。
        }
        return map;
    }
}
cloud-server-other/src/main/java/com/dsh/other/util/ResultUtil.java
@@ -3,7 +3,6 @@
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
/**
 * 定义统一返回对象
@@ -107,8 +106,8 @@
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", new JSONObject());
    public static  ResultUtil paranErr(String ages){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "【" + ages + "】参数异常", new JSONObject());
    }
    /**
@@ -116,11 +115,10 @@
     * @return
     */
    public static <T> ResultUtil<T> paranErr(T data){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "SYSTEM_RUN_ERROR", data);
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", data);
    }
    @Autowired
    private static MessageUtils messageUtils;
    /**
     * 运行异常
     * @return
cloud-server-other/src/main/java/com/dsh/other/util/TokenUtil.java
@@ -2,6 +2,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@@ -12,7 +14,9 @@
    private RedisUtil redisUtil;
    public Integer getUserIdFormRedis(HttpServletRequest request) throws Exception {
    public Integer getUserIdFormRedis() throws Exception {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String requestHeader = request.getHeader("Authorization");
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            requestHeader = requestHeader.substring(requestHeader.indexOf(" ") + 1);
cloud-server-other/src/main/java/com/dsh/other/util/httpClinet/HttpClientUtil.java
New file
@@ -0,0 +1,267 @@
package com.dsh.other.util.httpClinet;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * http工具类
 */
public class HttpClientUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    private static PoolingHttpClientConnectionManager connectionManager;
    {
        //1.创建连接池管理器
        connectionManager = new PoolingHttpClientConnectionManager(60000,
                TimeUnit.MILLISECONDS);
        connectionManager.setMaxTotal(1000);
        connectionManager.setDefaultMaxPerRoute(50);
    }
    /**
     * 创建一个httpClient对象
     */
    private static CloseableHttpClient getHttpCline(){
        return  HttpClients.custom()
                .setConnectionManager(connectionManager)
                .disableAutomaticRetries()
                .build();
    }
    private static RequestConfig getRequestConfig(){
        RequestConfig.Builder builder = RequestConfig.custom();
        builder.setSocketTimeout(60000)//3.1设置客户端等待服务端返回数据的超时时间
                .setConnectTimeout(30000)//3.2设置客户端发起TCP连接请求的超时时间
                .setExpectContinueEnabled(true)
                .setConnectionRequestTimeout(30000);//3.3设置客户端从连接池获取链接的超时时间
        return builder.build();
    }
    /**
     * 创建一个POST请求实例
     * @param url       请求地址
     * @param params    请求参数
     */
    private static CloseableHttpResponse setPostHttpRequset(String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        if(null != header){
            for(String key : header.keySet()){
                httpPost.setHeader(key, header.get(key));
            }
        }
        List<NameValuePair> list = new ArrayList<>();
        if(null != params){
            Set<String> keys = params.keySet();
            for(String key : keys){
                list.add(new BasicNameValuePair(key, null == params.get(key) ? null : params.get(key).toString()));
            }
        }
        switch (contentType){
            case "form":
                httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
                break;
            case "json":
                ObjectMapper objectMapper = new ObjectMapper();
                String s =objectMapper.writeValueAsString(params);
                httpPost.setEntity(new StringEntity(s, ContentType.create(ContentType.APPLICATION_JSON.getMimeType(), Charset.forName("UTF-8"))));
                break;
        }
        return getHttpCline().execute(httpPost);
    }
    /**
     * 获取get请求实例
     * @param url       请求地址
     * @param params    请求参数
     */
    private static CloseableHttpResponse setGetHttpRequset(String url, Map<String, Object> params, Map<String, String> header) throws Exception{
        StringBuffer sb = new StringBuffer();
        String p = "";
        if(null != params){
            Set<String> keys = params.keySet();
            for(String key : keys){
                sb.append(key + "=" + params.get(key) + "&");
            }
            p = "?" + sb.substring(0, sb.length() - 1);
        }
        HttpGet httpGet = new HttpGet(url + p);
        httpGet.setConfig(getRequestConfig());
        if(null != header){
            for(String key : header.keySet()){
                httpGet.setHeader(key, header.get(key));
            }
        }
        return getHttpCline().execute(httpGet);
    }
    /**
     * 发送http请求
     * @param mothed        "GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS"
     * @param url           请求地址
     * @param params        请求参数
     * @param header        请求头
     * @param contentType   参数请求方式form/json
     * @return
     */
    public static HttpResult pushHttpRequset(String mothed, String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception{
        String randome = UUID.randomUUID().toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
        logger.info(sdf.format(new Date()) + "----(" + randome + ")请求参数:" + JSON.toJSONString(params));
        CloseableHttpResponse httpResponse = null;
        switch (mothed){
            case "GET":
                httpResponse = setGetHttpRequset(url, params, header);
                break;
            case "POST":
                httpResponse = setPostHttpRequset(url, params, header, contentType);
                break;
        }
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        logger.info(sdf.format(new Date()) + "----(" + randome + ")返回结果:" + content);
        HttpResult httpResult = HttpResult.getHttpResult(statusCode, content);
        close(httpResponse);
        return httpResult;
    }
    /**
     * 发送XML请求
     * @param url       请求地址
     * @param xml       XML数据
     * @param header    自定义请求头
     * @return
     */
    public static HttpResult pushHttpRequsetXml(String url, String xml, Map<String, String> header) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        for(String key : header.keySet()){
            httpPost.setHeader(key, header.get(key));
        }
        httpPost.setHeader("Content-Type", "application/xml");
        httpPost.setEntity(new StringEntity(xml, "UTF-8"));
        CloseableHttpResponse httpResponse = getHttpCline().execute(httpPost);
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        HttpResult httpResult = HttpResult.getHttpResult(statusCode, content);
        close(httpResponse);
        return httpResult;
    }
    /**
     * 请求https发送XML请求
     * @param url           接口路径
     * @param xml           内容
     * @param header        请求头
     * @param certPassword      证书密码
     * @param certPath      证书路径
     * @param certType      证书类型
     * @return
     * @throws Exception
     */
    public String pushHttpsRequsetXml(String url, String xml, Map<String, String> header, String certPassword, String certPath, String certType) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        for(String key : header.keySet()){
            httpPost.setHeader(key, header.get(key));
        }
        httpPost.setHeader("Content-Type", "application/xml");
        httpPost.setEntity(new StringEntity(xml, "UTF-8"));
        CloseableHttpClient httpCline = this.initCert(certPassword, certPath, certType);
        CloseableHttpResponse httpResponse = httpCline.execute(httpPost);
        String content = null;
        if(httpResponse.getStatusLine().getStatusCode() == 200){
            content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        }else{
            content = "返回状态码:" + httpResponse.getStatusLine() + "。" + EntityUtils.toString(httpResponse.getEntity());
        }
        this.close(httpResponse);
        httpCline.close();
        return content;
    }
    /**
     * 初始化https对象(带证书)
     * @param key       证书密码
     * @param certPath  证书路径
     * @param certType  证书类型
     * @throws Exception
     */
    private CloseableHttpClient initCert(String key, String certPath, String certType) throws Exception {
        KeyStore keyStore = KeyStore.getInstance(certType);
        InputStream inputStream = new FileInputStream(new File(certPath));
        try {
            keyStore.load(inputStream, key.toCharArray());
        } finally {
            inputStream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();
        SSLConnectionSocketFactory sslsf =
                new SSLConnectionSocketFactory(sslcontext, new String[] {"TLSv1"}, null,
                        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }
    /**
     * 关闭资源
     */
    private static void close(CloseableHttpResponse httpResponse){
        try {
            if(null != httpResponse){
                EntityUtils.consume(httpResponse.getEntity());//此处高能,通过源码分析,由EntityUtils是否回收HttpEntity
                httpResponse.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if(null != httpResponse){
                    httpResponse.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
cloud-server-other/src/main/java/com/dsh/other/util/httpClinet/HttpResult.java
New file
@@ -0,0 +1,31 @@
package com.dsh.other.util.httpClinet;
import lombok.Data;
/**
 * http请求返回封装
 */
@Data
public class HttpResult {
    /**
     * 返回状态码
     */
    private Integer code;
    /**
     * 返回结果
     */
    private String data;
    /**
     * 返回封装结果
     * @param code
     * @param data
     * @return
     */
    public static HttpResult getHttpResult(Integer code, String data){
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(code);
        httpResult.setData(data);
        return httpResult;
    }
}