cloud-server-activity/pom.xml
@@ -14,6 +14,17 @@ <name>福利</name> <description>福利</description> <dependencies> <!-- 微信支付V3 目前新版本--> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.4.9</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10.10</version> </dependency> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> @@ -94,6 +105,12 @@ <artifactId>geodesy</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java-core</artifactId> <version>0.2.12</version> <scope>compile</scope> </dependency> </dependencies> <build> cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminController.java
@@ -1,5 +1,6 @@ package com.dsh.activity.controller; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -37,8 +38,11 @@ import javax.annotation.Resource; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.TextStyle; import java.util.*; import java.util.stream.Collectors; @@ -94,35 +98,37 @@ @ApiImplicitParam(value = "绑定学员ids多,个逗号拼接", name = "studentIds", dataType = "String", required = true), @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") }) public ResultUtil<THuiminCard> payHuiminCard(Integer id,Integer payType,String studentIds) { public ResultUtil<THuiminCard> payHuiminCard(Integer id, Integer payType, String studentIds) { try { Integer uid = tokenUtil.getUserIdFormRedis(); if (null == uid) { return ResultUtil.tokenErr(); } THuiminCard huiminCard = huiminCardService.getById(id); if (huiminCard.getEndTime()!=null && huiminCard.getEndTime().before(new Date())){ if (huiminCard.getEndTime() != null && huiminCard.getEndTime().before(new Date())) { return ResultUtil.error("该惠民卡已过期"); } if (huiminCard.getGrantCount()!=null){ if (huiminCard.getGrantCount()<=payHuiminService.lambdaQuery().eq(TPayHuimin::getCardId, huiminCard.getId()) .eq(TPayHuimin::getStatus,2).count()){ if (huiminCard.getGrantCount() != null) { if (huiminCard.getGrantCount() <= payHuiminService.lambdaQuery().eq(TPayHuimin::getCardId, huiminCard.getId()) .eq(TPayHuimin::getStatus, 2).count()) { return ResultUtil.error("该惠民卡已售完"); } } if (huiminCard.getLimitCount()!=null){ if (huiminCard.getLimitCount()<=payHuiminService.lambdaQuery().eq(TPayHuimin::getCardId, huiminCard.getId()) .eq(TPayHuimin::getStatus,2) if (huiminCard.getLimitCount() != null) { if (huiminCard.getLimitCount() <= payHuiminService.lambdaQuery().eq(TPayHuimin::getCardId, huiminCard.getId()) .eq(TPayHuimin::getStatus, 2) .eq(TPayHuimin::getAppUserId, uid) .count()){ .count()) { return ResultUtil.error("该惠民卡购买次数已达上限"); } } TPayHuimin tPayHuimin = new TPayHuimin(); tPayHuimin.setSalesMoney(huiminCard.getSalesMoney()); String[] split = studentIds.split(","); tPayHuimin.setSalesMoney(huiminCard.getSalesMoney().multiply(new BigDecimal(split.length)).setScale(2)); tPayHuimin.setAppUserId(uid); tPayHuimin.setStudentId(studentIds); switch (huiminCard.getHuiMinType()){ switch (huiminCard.getHuiMinType()) { case 1: // 年度卡 LocalDateTime localDateTime = LocalDateTime.now().plusDays(365); @@ -148,16 +154,16 @@ tPayHuimin.setCardId(huiminCard.getId()); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); tPayHuimin.setCode(sdf.format(new Date()) + UUIDUtil.getNumberRandom(5)); System.err.println("支付数据"+tPayHuimin); System.err.println("支付数据" + tPayHuimin); payHuiminService.save(tPayHuimin); BigDecimal bigDecimal = new BigDecimal(studentIds.split(",").length); switch (payType){ switch (payType) { case 1: return payMoneyUtil.weixinpay("购买惠民卡"+"-"+0, "", tPayHuimin.getCode(), tPayHuimin.getSalesMoney().multiply(bigDecimal).toString(), return payMoneyUtil.weixinpay("购买惠民卡" + "-" + 0, "", tPayHuimin.getCode(), tPayHuimin.getSalesMoney().toString(), "/base/huimin/callBack/weixinPayHuiminCallback", "APP", ""); case 2: String string = tPayHuimin.getSalesMoney().multiply(bigDecimal).setScale(2).toString(); return payMoneyUtil.alipay(smid,"购买惠民卡", "购买惠民卡", "", tPayHuimin.getCode(), string, String string = tPayHuimin.getSalesMoney().toString(); return payMoneyUtil.alipay(smid, "购买惠民卡", "购买惠民卡", "", tPayHuimin.getCode(), string, "/base/huimin/callBack/aliPayHuiminCallback"); } @@ -180,7 +186,7 @@ @ApiImplicitParam(value = "门店id", name = "storeId", dataType = "int", required = true), @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") }) public ResultUtil<THuiminCard> getHuiminCardDetail(Integer id,Integer storeId) { public ResultUtil<THuiminCard> getHuiminCardDetail(Integer id, Integer storeId) { try { Integer uid = tokenUtil.getUserIdFormRedis(); if (null == uid) { @@ -189,54 +195,54 @@ THuiminCard huiminCard = huiminCardService.getById(id); List<TPayHuimin> payHuimins = payHuiminService.list(new LambdaQueryWrapper<TPayHuimin>() .eq(TPayHuimin::getAppUserId, uid) .ge(TPayHuimin::getEndTime,new Date()) .ge(TPayHuimin::getEndTime, new Date()) .eq(TPayHuimin::getStatus, 1)); List<TPayHuimin> collect = payHuimins.stream().filter(e -> e.getCardId().equals(huiminCard.getId())).collect(Collectors.toList()); if (!collect.isEmpty()){ if (!collect.isEmpty()) { huiminCard.setIsBuy(1); }else{ } else { huiminCard.setIsBuy(0); } List<Store> stores = storeClient.queryStoreByIds(Collections.singletonList(storeId)); if (!stores.isEmpty()){ Store store = stores.get(0); Integer operatorId = store.getOperatorId(); if (operatorId==null||operatorId==0){ // 平台门店 THuiminAgreement huiminAgreement = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() List<Store> stores = storeClient.queryStoreByIds(Collections.singletonList(storeId)); if (!stores.isEmpty()) { Store store = stores.get(0); Integer operatorId = store.getOperatorId(); if (operatorId == null || operatorId == 0) { // 平台门店 THuiminAgreement huiminAgreement = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .isNull(THuiminAgreement::getOperatorId)); if (huiminAgreement != null) { List<THuiminAgreementSetting> list = huiminAgreementSettingService.list(new LambdaQueryWrapper<THuiminAgreementSetting>() .eq(THuiminAgreementSetting::getAgreementId, huiminAgreement.getId())); huiminCard.setAgreementSettings(list); } else { huiminCard.setAgreementSettings(new ArrayList<>()); } } else { // 运营商门店 THuiminAgreement huiminAgreement = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .eq(THuiminAgreement::getOperatorId, operatorId)); if (huiminAgreement != null) { List<THuiminAgreementSetting> list = huiminAgreementSettingService.list(new LambdaQueryWrapper<THuiminAgreementSetting>() .eq(THuiminAgreementSetting::getAgreementId, huiminAgreement.getId())); huiminCard.setAgreementSettings(list); } else { THuiminAgreement huiminAgreement1 = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .isNull(THuiminAgreement::getOperatorId)); if (huiminAgreement!=null){ if (huiminAgreement1 != null) { List<THuiminAgreementSetting> list = huiminAgreementSettingService.list(new LambdaQueryWrapper<THuiminAgreementSetting>() .eq(THuiminAgreementSetting::getAgreementId, huiminAgreement.getId())); .eq(THuiminAgreementSetting::getAgreementId, huiminAgreement1.getId())); huiminCard.setAgreementSettings(list); }else { } else { huiminCard.setAgreementSettings(new ArrayList<>()); } }else{ // 运营商门店 THuiminAgreement huiminAgreement = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .eq(THuiminAgreement::getOperatorId,operatorId)); if (huiminAgreement!=null){ List<THuiminAgreementSetting> list = huiminAgreementSettingService.list(new LambdaQueryWrapper<THuiminAgreementSetting>() .eq(THuiminAgreementSetting::getAgreementId, huiminAgreement.getId())); huiminCard.setAgreementSettings(list); }else { THuiminAgreement huiminAgreement1 = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .isNull(THuiminAgreement::getOperatorId)); if (huiminAgreement1!=null){ List<THuiminAgreementSetting> list = huiminAgreementSettingService.list(new LambdaQueryWrapper<THuiminAgreementSetting>() .eq(THuiminAgreementSetting::getAgreementId, huiminAgreement1.getId())); huiminCard.setAgreementSettings(list); }else { huiminCard.setAgreementSettings(new ArrayList<>()); } } } }else{ huiminCard.setAgreementSettings(new ArrayList<>()); } } else { huiminCard.setAgreementSettings(new ArrayList<>()); } return ResultUtil.success(huiminCard); } catch (Exception e) { @@ -244,6 +250,7 @@ return ResultUtil.success(); } } /** * 惠民卡富文本内容-惠民卡列表 */ @@ -256,39 +263,40 @@ @ApiImplicitParam(value = "门店id", name = "storeId", dataType = "int", required = true), @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") }) public ResultUtil<HuiminAgreementVO> getHuiminAgreementAndList(Integer pageSize, Integer pageNo,Integer storeId) { public ResultUtil<HuiminAgreementVO> getHuiminAgreementAndList(Integer pageSize, Integer pageNo, Integer storeId) { try { Integer uid = tokenUtil.getUserIdFormRedis(); if (null == uid) { return ResultUtil.tokenErr(); } pageNo = (pageNo - 1) * pageSize; HuiminAgreementVO huiminAgreementVO = new HuiminAgreementVO(); List<THuiminCard> cardList = huiminCardService.getHuiminAgreementAndList(pageNo,pageSize,storeId); List<THuiminCard> cardList = huiminCardService.getHuiminAgreementAndList(pageNo, pageSize, storeId); List<THuiminCard> list = huiminCardService.list(); List<THuiminCard> cardListNolimit = huiminCardService.getHuiminAgreementAndListNolimit(storeId); if (cardListNolimit.isEmpty()){ if (cardListNolimit.isEmpty()) { // 没有配置惠民卡 展示富文本内容 huiminAgreementVO.setShowType(1); }else{ } else { huiminAgreementVO.setShowType(2); } List<Store> stores = storeClient.queryStoreByIds(Collections.singletonList(storeId)); Store store = stores.get(0); if (store.getOperatorId()==null || store.getOperatorId()==0){ if (store.getOperatorId() == null || store.getOperatorId() == 0) { // 平台 THuiminAgreement one = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .isNull(THuiminAgreement::getOperatorId).last("limit 1")); huiminAgreementVO.setIntroduce(one.getStoreNoHuiminCardIntro()); }else{ } else { THuiminAgreement one = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .eq(THuiminAgreement::getOperatorId,store.getOperatorId()).last("limit 1")); if (one == null){ .eq(THuiminAgreement::getOperatorId, store.getOperatorId()).last("limit 1")); if (one == null) { THuiminAgreement two = huiminAgreementService.getOne(new LambdaQueryWrapper<THuiminAgreement>() .isNull(THuiminAgreement::getOperatorId).last("limit 1")); huiminAgreementVO.setIntroduce(two.getStoreNoHuiminCardIntro()); }else{ } else { huiminAgreementVO.setIntroduce(one.getStoreNoHuiminCardIntro()); } @@ -297,37 +305,354 @@ List<TPayHuimin> payHuimins = payHuiminService.list(new LambdaQueryWrapper<TPayHuimin>() .eq(TPayHuimin::getAppUserId, uid) .ge(TPayHuimin::getEndTime,new Date()) .in(TPayHuimin::getStatus, Arrays.asList(2,3))); .ge(TPayHuimin::getEndTime, new Date()) .eq(TPayHuimin::getStatus, 2)); List<HuiminCardVO> huiminCardVOS = new ArrayList<>(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); List<TStudent> tStudents = studentClient.queryStudentList(uid); List<Integer> integers = new ArrayList<>(); for (TPayHuimin payHuimin : payHuimins) { if (integers.contains(payHuimin.getCardId())){ continue; } THuiminCard huiminCard = list.stream().filter(e -> e.getId().equals(payHuimin.getCardId())).findFirst().orElse(null); if (huiminCard == null) continue; HuiminCardVO huiminCardVO1 = new HuiminCardVO(); huiminCardVO1.setId(huiminCard.getId()); huiminCardVO1.setHuiminName(huiminCard.getHuiMinName()); huiminCardVO1.setCover(huiminCard.getBuyCover()); huiminCardVO1.setIsBuy(1); String siteIds = ""; if (huiminCard.getUseScope() == 2) { siteIds = huiminCard.getUseIds(); } else { siteIds = siteClient.querySiteByStoreIds(huiminCard.getStoreIds()) .stream() .map(Site::getId) .map(String::valueOf) .collect(Collectors.joining(",")); } String storeIds = huiminCard.getStoreIds(); if (storeIds.contains("2024")) { siteIds = siteIds + ",32"; } if (storeIds.contains("1001")) { siteIds = siteIds + ",3"; } // 门店ids JSONArray sid = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); // 场地ids JSONArray rid = JSONArray.parseArray(Arrays.toString(siteIds.split(","))); // 可用时间 LocalDate today = LocalDate.now(); int week = today.getDayOfWeek().getValue(); JSONArray time = JSONArray.parseArray(huiminCard.getUseWeeks()); JSONArray jsonArray = new JSONArray(); String string = LocalDate.now().toString(); Date date = new Date(); if (date.before(huiminCard.getEndTime()) && date.after(huiminCard.getStartTime())) { for (Object o : time) { JSONObject jsonObject = (JSONObject) o; for (Object days : jsonObject.getJSONArray("days")) { JSONObject jsonObject1 = (JSONObject) days; if (jsonObject1.getString("value").equals(String.valueOf(week)) && jsonObject1.getBoolean("checked")) { JSONObject jsonObject2 = new JSONObject(); String s1 = string + " " + jsonObject.getString("startTime") + ":00"; String e1 = string + " " + jsonObject.getString("endTime") + ":00"; // 转化为Date类型 Date start = DateUtil.parse(s1, "yyyy-MM-dd HH:mm:ss"); Date end = DateUtil.parse(e1, "yyyy-MM-dd HH:mm:ss"); if (new Date().after(start) && new Date().before(end)) { // jsonObject2.put("start_time", start.getTime() / 1000); Date date1 = new Date(); jsonObject2.put("start_time", date1.getTime() / 1000); date1.setTime(date1.getTime() + 30 * 1000); if (start.before(end)) { jsonObject2.put("end_time", date1.getTime() / 1000); jsonArray.add(jsonObject2); } } } } } } if (!jsonArray.isEmpty()) { huiminCardVO1.setEndTime(simpleDateFormat.format(payHuimin.getEndTime())); TStudent tStudent = tStudents.stream().filter(e -> e.getId().equals(Integer.valueOf(payHuimin.getStudentId().split(",")[0]))).findFirst().orElse(null); if (tStudent!=null){ huiminCardVO1.setStudentName(tStudent.getName()); } String temp = "{\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + payHuimin.getStudentId().split(",")[0] + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; huiminCardVO1.setQrCode(temp); huiminCardVOS.add(huiminCardVO1); integers.add(payHuimin.getCardId()); } } for (THuiminCard huiminCardVO : cardList) { HuiminCardVO huiminCardVO1 = new HuiminCardVO(); huiminCardVO1.setId(huiminCardVO.getId()); List<TPayHuimin> collect = payHuimins.stream().filter(e -> e.getCardId().equals(huiminCardVO.getId())).collect(Collectors.toList()); if (!collect.isEmpty()){ if (!collect.isEmpty()) { for (TPayHuimin tPayHuimin : collect) { if (tPayHuimin.getStatus().equals(2)){ if (tPayHuimin.getStatus().equals(2)) { huiminCardVO1.setCover(huiminCardVO.getBuyCover()); huiminCardVO1.setIsBuy(1); break; }else{ } else { huiminCardVO1.setCover(huiminCardVO.getUnBuyCover()); huiminCardVO1.setIsBuy(0); } } }else{ } else { huiminCardVO1.setCover(huiminCardVO.getUnBuyCover()); huiminCardVO1.setIsBuy(0); } huiminCardVOS.add(huiminCardVO1); } huiminAgreementVO.setCardList(huiminCardVOS); // 手动对huiminCardVOS进行分页 if (pageNo < 1) { pageNo = 1; } if (pageSize < 1) { pageSize = 10; // 默认每页10条 } int startIndex = (pageNo - 1) * pageSize; int endIndex = Math.min(startIndex + pageSize, huiminCardVOS.size()); // 防止 startIndex 超过 huiminCardVOS.size() if (startIndex > huiminCardVOS.size()) { startIndex = huiminCardVOS.size(); } List<HuiminCardVO> paginatedHuiminCardVOS = huiminCardVOS.subList(startIndex, endIndex); // 将分页后的数据设置到 huiminAgreementVO 中 huiminAgreementVO.setCardList(paginatedHuiminCardVOS); // 将分页后的数据设置到 huiminAgreementVO 中 huiminAgreementVO.setCardList(paginatedHuiminCardVOS); // huiminAgreementVO.setCardList(huiminCardVOS); return ResultUtil.success(huiminAgreementVO); } catch (Exception e) { e.printStackTrace(); return ResultUtil.success(new HuiminAgreementVO()); } } /** * 惠民卡列表-根据惠民卡获取已购买绑定惠民卡的学员列表 */ @ResponseBody @PostMapping("/getStudentListByCarId") @ApiOperation(value = "惠民卡列表-根据惠民卡获取已购买绑定惠民卡的学员列表") @ApiImplicitParams({ @ApiImplicitParam(value = "惠民卡id", name = "id", dataType = "int", required = true), @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") }) public ResultUtil<List<TStudent>> getStudentListByCarId(Integer id) { try { Integer uid = tokenUtil.getUserIdFormRedis(); if (null == uid) { return ResultUtil.tokenErr(); } List<TPayHuimin> payHuimins = payHuiminService.list(new LambdaQueryWrapper<TPayHuimin>() .eq(TPayHuimin::getAppUserId, uid) .eq(TPayHuimin::getCardId, id) .ge(TPayHuimin::getEndTime, new Date()) .eq(TPayHuimin::getStatus, 2)); List<THuiminCard> huiminCards = huiminCardService.list(); List<Integer> studentIds = new ArrayList<>(); for (TPayHuimin payHuimin : payHuimins) { THuiminCard huiminCard = huiminCards.stream().filter(e -> e.getId().equals(payHuimin.getCardId())).findFirst().orElse(null); if (huiminCard != null) { String siteIds = ""; if (huiminCard.getUseScope() == 2) { siteIds = huiminCard.getUseIds(); } else { siteIds = siteClient.querySiteByStoreIds(huiminCard.getStoreIds()) .stream() .map(Site::getId) .map(String::valueOf) .collect(Collectors.joining(",")); } String storeIds = huiminCard.getStoreIds(); if (storeIds.contains("2024")) { siteIds = siteIds + ",32"; } if (storeIds.contains("1001")) { siteIds = siteIds + ",3"; } // 门店ids JSONArray sid = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); // 场地ids JSONArray rid = JSONArray.parseArray(Arrays.toString(siteIds.split(","))); // 可用时间 LocalDate today = LocalDate.now(); int week = today.getDayOfWeek().getValue(); JSONArray time = JSONArray.parseArray(huiminCard.getUseWeeks()); JSONArray jsonArray = new JSONArray(); String string = LocalDate.now().toString(); Date date = new Date(); if (date.before(huiminCard.getEndTime()) && date.after(huiminCard.getStartTime())) { for (Object o : time) { JSONObject jsonObject = (JSONObject) o; for (Object days : jsonObject.getJSONArray("days")) { JSONObject jsonObject1 = (JSONObject) days; if (jsonObject1.getString("value").equals(String.valueOf(week)) && jsonObject1.getBoolean("checked")) { JSONObject jsonObject2 = new JSONObject(); String s1 = string + " " + jsonObject.getString("startTime") + ":00"; String e1 = string + " " + jsonObject.getString("endTime") + ":00"; // 转化为Date类型 Date start = DateUtil.parse(s1, "yyyy-MM-dd HH:mm:ss"); Date end = DateUtil.parse(e1, "yyyy-MM-dd HH:mm:ss"); if (new Date().after(start) && new Date().before(end)) { // jsonObject2.put("start_time", start.getTime() / 1000); Date date1 = new Date(); jsonObject2.put("start_time", date1.getTime() / 1000); date1.setTime(date1.getTime() + 30 * 1000); if (start.before(end)) { jsonObject2.put("end_time", date1.getTime() / 1000); jsonArray.add(jsonObject2); } } } } } } if (!jsonArray.isEmpty()) { // 将学员加入 String[] split = payHuimin.getStudentId().split(","); for (String s : split) { studentIds.add(Integer.valueOf(s)); } } } } String collect = studentIds.stream().map(String::valueOf).collect(Collectors.joining(",")); List<TStudent> studentByIds = studentClient.getStudentByIds(collect); return ResultUtil.success(studentByIds); } catch (Exception e) { throw new RuntimeException(e); } } /** * 惠民卡列表-选择学员后返回对应的二维码生成规则和有效期结束时间 */ @ResponseBody @PostMapping("/getQrCodeByStudentId") @ApiOperation(value = "惠民卡列表-选择学员后返回对应的二维码生成规则和有效期结束时间") @ApiImplicitParams({ @ApiImplicitParam(value = "惠民卡id", name = "cardId", dataType = "int", required = true), @ApiImplicitParam(value = "学员id", name = "studentId", dataType = "int", required = true), @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") }) public ResultUtil<HuiminCardStudentVO> getQrCodeByStudentId(Integer cardId, Integer studentId) { try { Integer uid = tokenUtil.getUserIdFormRedis(); if (null == uid) { return ResultUtil.tokenErr(); } List<TStudent> tStudents = studentClient.queryStudentList(uid); List<TPayHuimin> payHuimins = payHuiminService.list(new LambdaQueryWrapper<TPayHuimin>() .apply("FIND_IN_SET(" + studentId + ", studentId) > 0") // .eq(TPayHuimin::getStudentId, studentId) .eq(TPayHuimin::getCardId, cardId) .ge(TPayHuimin::getEndTime, new Date()) .eq(TPayHuimin::getStatus, 2) .orderByDesc(TPayHuimin::getEndTime)); HuiminCardStudentVO huiminCardStudentVO = new HuiminCardStudentVO(); if (!payHuimins.isEmpty()) { TPayHuimin tPayHuimin = payHuimins.get(0); THuiminCard huiminCard = huiminCardService.getById(cardId); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); huiminCardStudentVO.setEndTime(simpleDateFormat.format(tPayHuimin.getEndTime())); String siteIds = ""; if (huiminCard.getUseScope() == 2) { siteIds = huiminCard.getUseIds(); } else { siteIds = siteClient.querySiteByStoreIds(huiminCard.getStoreIds()) .stream() .map(Site::getId) .map(String::valueOf) .collect(Collectors.joining(",")); } String storeIds = huiminCard.getStoreIds(); if (storeIds.contains("2024")) { siteIds = siteIds + ",32"; } if (storeIds.contains("1001")) { siteIds = siteIds + ",3"; } // 门店ids JSONArray sid = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); // 场地ids JSONArray rid = JSONArray.parseArray(Arrays.toString(siteIds.split(","))); // 可用时间 LocalDate today = LocalDate.now(); int week = today.getDayOfWeek().getValue(); JSONArray time = JSONArray.parseArray(huiminCard.getUseWeeks()); JSONArray jsonArray = new JSONArray(); String string = LocalDate.now().toString(); Date date = new Date(); if (date.before(huiminCard.getEndTime()) && date.after(huiminCard.getStartTime())) { for (Object o : time) { JSONObject jsonObject = (JSONObject) o; for (Object days : jsonObject.getJSONArray("days")) { JSONObject jsonObject1 = (JSONObject) days; if (jsonObject1.getString("value").equals(String.valueOf(week)) && jsonObject1.getBoolean("checked")) { JSONObject jsonObject2 = new JSONObject(); String s1 = string + " " + jsonObject.getString("startTime") + ":00"; String e1 = string + " " + jsonObject.getString("endTime") + ":00"; // 转化为Date类型 Date start = DateUtil.parse(s1, "yyyy-MM-dd HH:mm:ss"); Date end = DateUtil.parse(e1, "yyyy-MM-dd HH:mm:ss"); jsonObject2.put("start_time", start.getTime() / 1000); start.setTime(start.getTime() + 30 * 1000); if (new Date().after(start) && new Date().before(end)) { // jsonObject2.put("start_time", start.getTime() / 1000); Date date1 = new Date(); jsonObject2.put("start_time", date1.getTime() / 1000); date1.setTime(date1.getTime() + 30 * 1000); if (start.before(end)) { jsonObject2.put("end_time", date1.getTime() / 1000); jsonArray.add(jsonObject2); } } } } } } String temp = "{\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + studentId + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; huiminCardStudentVO.setQrCode(temp); TStudent tStudent = tStudents.stream().filter(e -> e.getId().equals(studentId)).findFirst().orElse(null); if (tStudent!=null){ huiminCardStudentVO.setStudentName(tStudent.getName()); } } return ResultUtil.success(huiminCardStudentVO); } catch (Exception e) { throw new RuntimeException(e); } } /** * 惠民卡富文本内容-惠民卡列表 */ @@ -346,36 +671,34 @@ return ResultUtil.tokenErr(); } pageNo = (pageNo - 1) * pageSize; List<MyHuiminCardVO> cardList = huiminCardService.getMyHuiminCardList(pageNo,pageSize,uid); List<MyHuiminCardVO> cardList = huiminCardService.getMyHuiminCardList(pageNo, pageSize, uid); List<THuiminCard> list = huiminCardService.list(); for (MyHuiminCardVO myHuiminCardVO : cardList) { TPayHuimin byId = payHuiminService.getById(myHuiminCardVO.getId()); myHuiminCardVO.setEndTime(byId.getEndTime()); myHuiminCardVO.setSalesMoney(byId.getSalesMoney()); int count = huiminRecordService.count(new LambdaQueryWrapper<THuiminRecord>() .eq(THuiminRecord::getHuiminCardId, myHuiminCardVO.getCardId())); // 购卡7日内没有使用记录可退款。超过7日不管有没有使用记录都不能退款 if (new Date().after(DateUtil.addDay(myHuiminCardVO.getPaymentTime(),7))){ if (new Date().after(DateUtil.addDay(myHuiminCardVO.getPaymentTime(), 7))) { // 超过七天不可退款 myHuiminCardVO.setIsRefund(0); }else if (count>=7){ } else if (count >= 7) { myHuiminCardVO.setIsRefund(0); }else{ } else { myHuiminCardVO.setIsRefund(1); } THuiminCard huiminCard = list.stream().filter(e -> e.getId().equals(myHuiminCardVO.getCardId())).findFirst().orElse(null); if (null!=huiminCard){ if (null != huiminCard) { myHuiminCardVO.setCover(huiminCard.getBuyCover()); } if (myHuiminCardVO.getEndTime().before(new Date())){ if (myHuiminCardVO.getEndTime().before(new Date())) { // 已过期 myHuiminCardVO.setIsExpire(1); if (null!=huiminCard){ if (null != huiminCard) { myHuiminCardVO.setCover(huiminCard.getUnBuyCover()); } }else{ } else { myHuiminCardVO.setIsExpire(0); } // 查询绑定人员列表 @@ -388,6 +711,7 @@ return ResultUtil.success(new ArrayList<>()); } } /** * 个人中心-我的惠民卡-退款 */ @@ -405,35 +729,35 @@ return ResultUtil.tokenErr(); } TPayHuimin tPayHuimin = payHuiminService.getById(id); if (tPayHuimin==null){ if (tPayHuimin == null) { return ResultUtil.error("订单不存在"); } if (tPayHuimin.getStatus()==3 && tPayHuimin.getRefundStatus()!=1){ if (tPayHuimin.getStatus() == 3 && tPayHuimin.getRefundStatus() != 1) { return ResultUtil.error("不可重复退款"); } if (tPayHuimin.getEndTime().before(new Date())){ if (tPayHuimin.getEndTime().before(new Date())) { // 已过期 return ResultUtil.error("惠民卡已过期,不可退款"); } int count = huiminRecordService.count(new LambdaQueryWrapper<THuiminRecord>() .eq(THuiminRecord::getHuiminCardId, tPayHuimin.getCardId())); // 购卡7日内没有使用记录可退款。超过7日不管有没有使用记录都不能退款 if (new Date().after(DateUtil.addDay(tPayHuimin.getPaymentTime(),7))){ if (new Date().after(DateUtil.addDay(tPayHuimin.getPaymentTime(), 7))) { // 超过七天不可退款 return ResultUtil.error("惠民卡购买超过七天,不可退款"); }else if (count>=7){ } else if (count >= 7) { // 使用记录大于等于7次不可退款 return ResultUtil.error("惠民卡使用记录大于等于7次,不可退款"); } if (tPayHuimin.getPaymentType()==1){ if (tPayHuimin.getPaymentType() == 1) { Map<String, String> map = payMoneyUtil.wxRefund(tPayHuimin.getOrderNumber(), tPayHuimin.getCode(), tPayHuimin.getSalesMoney().toString(), tPayHuimin.getSalesMoney().toString(), "/base/huimin/callBack/wxRefundHuiminCallback"); if(!"SUCCESS".equals(map.get("return_code"))){ if (!"SUCCESS".equals(map.get("return_code"))) { System.err.println("-------------微信退款失败---------"); System.err.println(map.get("return_msg")); return ResultUtil.error("微信退款失败"); } }else{ } else { Map<String, String> map = payMoneyUtil.aliRefund(tPayHuimin.getOrderNumber(), tPayHuimin.getSalesMoney().toString()); String return_code = map.get("code"); if (!"10000".equals(return_code)) { @@ -462,10 +786,61 @@ // String format = simpleDateFormat.format(date); // System.err.println(format); String storeIds = "1001,1002"; JSONArray jsonArray = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); System.err.println(jsonArray); // String storeIds = "1001,1002"; // JSONArray jsonArray = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); // System.err.println(jsonArray); // // // 获取当前日期 // LocalDate today = LocalDate.now(); // // // 获取当前日期是周几 // DayOfWeek dayOfWeek = today.getDayOfWeek(); // // // 输出当前是周几,使用中文显示 // System.out.println("今天是: " + dayOfWeek.getValue()); Date start = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.err.println(simpleDateFormat.format(start)); start.setTime(start.getTime() + 30 * 1000); System.err.println(simpleDateFormat.format(start)); // String temp = "[{\"days\":[{\"value\":\"1\",\"label\":\"星期一\",\"checked\":true},{\"value\":\"2\",\"label\":\"星期二\",\"checked\":true},{\"value\":\"3\",\"label\":\"星期三\",\"checked\":true},{\"value\":\"4\",\"label\":\"星期四\",\"checked\":true},{\"value\":\"5\",\"label\":\"星期五\",\"checked\":true},{\"value\":\"6\",\"label\":\"星期六\",\"checked\":false},{\"value\":\"7\",\"label\":\"星期日\",\"checked\":false}],\"startTime\":\"00:00\",\"endTime\":\"23:59\"}]"; // // 可用时间 // LocalDate today = LocalDate.now(); // // int week = today.getDayOfWeek().getValue(); // // JSONArray time = JSONArray.parseArray(temp); // int i = 0; // JSONArray jsonArray = new JSONArray(); // // StringBuilder startTime = new StringBuilder(); // StringBuilder endTime = new StringBuilder(); // // String string = LocalDate.now().toString(); // // for (Object o : time) { // JSONObject jsonObject = (JSONObject) o; // for (Object days : jsonObject.getJSONArray("days")) { // JSONObject jsonObject1 = (JSONObject) days; // if (jsonObject1.getString("value").equals(String.valueOf(week))&&jsonObject1.getBoolean("checked")){ // JSONObject jsonObject2 = new JSONObject(); // String s1 = string+" "+jsonObject.getString("startTime")+":00"; // String e1 = string+" "+jsonObject.getString("endTime")+":00"; // // 转化为Date类型 // Date start = DateUtil.parse(s1,"yyyy-MM-dd HH:mm:ss"); // Date end = DateUtil.parse(e1,"yyyy-MM-dd HH:mm:ss"); // jsonObject2.put("startTime",start.getTime()); // jsonObject2.put("endTime",end.getTime()); // jsonArray.add(jsonObject2); // } // // // } // i++; // } // System.err.println(jsonArray); } /** * 个人中心-我的惠民卡-查看详情 */ @@ -483,15 +858,19 @@ return ResultUtil.tokenErr(); } TPayHuimin tPayHuimin = payHuiminService.getById(id); if (tPayHuimin==null){ if (tPayHuimin == null) { return ResultUtil.error("惠民卡不存在"); } THuiminCard byId = huiminCardService.getById(tPayHuimin.getCardId()); MyHuiminCardDetailVO myHuiminCardDetailVO = new MyHuiminCardDetailVO(); List<TStudent> studentByIds1 = studentClient.getStudentByIds(tPayHuimin.getStudentId()); if (CollUtil.isNotEmpty(studentByIds1)) { myHuiminCardDetailVO.setStudentName(studentByIds1.get(0).getName()); } String siteIds = ""; if (byId.getUseScope()==2){ if (byId.getUseScope() == 2) { siteIds = byId.getUseIds(); }else{ } else { siteIds = siteClient.querySiteByStoreIds(byId.getStoreIds()) .stream() .map(Site::getId) @@ -499,8 +878,57 @@ .collect(Collectors.joining(",")); } String storeIds = byId.getStoreIds(); JSONArray jsonArray = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); String temp ="{\"sid\":\"" +siteIds+"\","+"\"useTimes:\"\""+byId.getUseWeeks()+"\","+"\"unUseTimes:\""+byId.getUnUseTimes()+"\"}"; if (storeIds.contains("2024")) { siteIds = siteIds + ",32"; } if (storeIds.contains("1001")) { siteIds = siteIds + ",3"; } // 门店ids JSONArray sid = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); // 场地ids JSONArray rid = JSONArray.parseArray(Arrays.toString(siteIds.split(","))); // 可用时间 LocalDate today = LocalDate.now(); int week = today.getDayOfWeek().getValue(); JSONArray time = JSONArray.parseArray(byId.getUseWeeks()); JSONArray jsonArray = new JSONArray(); String string = LocalDate.now().toString(); Date date = new Date(); if (date.before(byId.getEndTime()) && date.after(byId.getStartTime())) { for (Object o : time) { JSONObject jsonObject = (JSONObject) o; for (Object days : jsonObject.getJSONArray("days")) { JSONObject jsonObject1 = (JSONObject) days; if (jsonObject1.getString("value").equals(String.valueOf(week)) && jsonObject1.getBoolean("checked")) { JSONObject jsonObject2 = new JSONObject(); String s1 = string + " " + jsonObject.getString("startTime") + ":00"; String e1 = string + " " + jsonObject.getString("endTime") + ":00"; // 转化为Date类型 Date start = DateUtil.parse(s1, "yyyy-MM-dd HH:mm:ss"); Date end = DateUtil.parse(e1, "yyyy-MM-dd HH:mm:ss"); jsonObject2.put("start_time", start.getTime() / 1000); start.setTime(start.getTime() + 30 * 1000); if (new Date().after(start) && new Date().before(end)) { // jsonObject2.put("start_time", start.getTime() / 1000); Date date1 = new Date(); jsonObject2.put("start_time", date1.getTime() / 1000); date1.setTime(date1.getTime() + 30 * 1000); if (start.before(end)) { jsonObject2.put("end_time", date1.getTime() / 1000); jsonArray.add(jsonObject2); } } } } } } String temp = "{\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + tPayHuimin.getStudentId() + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; myHuiminCardDetailVO.setQrCode(temp); myHuiminCardDetailVO.setCardId(tPayHuimin.getCardId()); myHuiminCardDetailVO.setHuiminCard(byId); @@ -515,6 +943,7 @@ return ResultUtil.success(new MyHuiminCardDetailVO()); } } /** * 获取添加人员、选择人员说明文案 */ @@ -532,7 +961,7 @@ } THuiminAgreement one = huiminAgreementService.lambdaQuery() .isNull(THuiminAgreement::getOperatorId).last("limit 1").one(); return ResultUtil.success(one); return ResultUtil.success(one); } catch (Exception e) { e.printStackTrace(); return ResultUtil.success(new THuiminAgreement()); cloud-server-activity/src/main/java/com/dsh/activity/controller/WeiXinV3Controller.java
New file @@ -0,0 +1,76 @@ package com.dsh.activity.controller; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.dsh.activity.entity.*; import com.dsh.activity.feignclient.account.StudentClient; import com.dsh.activity.feignclient.other.SiteClient; import com.dsh.activity.feignclient.other.StoreClient; import com.dsh.activity.feignclient.other.model.Site; import com.dsh.activity.feignclient.other.model.Store; import com.dsh.activity.model.response.*; import com.dsh.activity.service.*; import com.dsh.activity.util.*; //import com.dsh.activity.util.wx.WechatPaymentService; import com.dsh.activity.util.wx.WxAppPayService; import io.swagger.annotations.Api; 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.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; /** * @author zhibing.pu * @date 2023/6/24 11:27 */ @RestController @RequestMapping("/base") public class WeiXinV3Controller { // @Resource // private WechatPaymentService wechatPaymentService; @Autowired private WxAppPayService wxAppPayService; @ResponseBody @PostMapping("/testWeiXinV3") @ApiOperation(value = "获取添加人员、选择人员说明文案") @ApiImplicitParams({ @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") }) public ResultUtil getContentForStudent() throws Exception { // Map<String, Object> stringObjectMap = wechatPaymentService.weChatDoUnifiedOrder(); // ... 在你的下单方法中调用 ... try { String description = "商品描述"; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String outTradeNo =sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); BigDecimal amount = new BigDecimal("0.01"); // 支付金额,例如1分钱 Map<String, String> payParams = wxAppPayService.createOrder(description, outTradeNo, amount); return ResultUtil.success(payParams); // 将 payParams 返回给你的APP前端,前端使用这些参数调起微信支付SDK // return ResponseEntity.ok(payParams); // 示例 } catch (Exception e) { // 处理异常 // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("下单失败"); } return ResultUtil.success(); } } cloud-server-activity/src/main/java/com/dsh/activity/model/response/HuiminCardStudentVO.java
New file @@ -0,0 +1,23 @@ package com.dsh.activity.model.response; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor @ApiModel(value = "根据学员id展示惠民卡二维码VO") public class HuiminCardStudentVO { @ApiModelProperty("有效期至") private String endTime; @ApiModelProperty("二维码规则") private String qrCode; @ApiModelProperty("学员名称") private String studentName; } cloud-server-activity/src/main/java/com/dsh/activity/model/response/HuiminCardVO.java
@@ -14,10 +14,18 @@ @ApiModelProperty("惠民卡id") private Integer id; @ApiModelProperty("惠民卡名称") private String huiminName; @ApiModelProperty("封面图") private String cover; @ApiModelProperty("是否购买 0否1是") private Integer isBuy; @ApiModelProperty("二维码规则") private String qrCode; @ApiModelProperty("有效期") private String endTime; @ApiModelProperty("学员姓名") private String studentName; cloud-server-activity/src/main/java/com/dsh/activity/model/response/MyHuiminCardDetailVO.java
@@ -30,6 +30,8 @@ private List<TStudent> studentList; @ApiModelProperty("惠民卡") private THuiminCard huiminCard; @ApiModelProperty("购买使用者名称") private String studentName; } cloud-server-activity/src/main/java/com/dsh/activity/util/PayMoneyUtil.java
@@ -61,8 +61,9 @@ private String key = "6f5e0c2dcabfa9c27b5da5836a362fef";//微信商户号 // private String callbackPath = "https://online.daowepark.com:443/activity";//支付回调网关地址 private String callbackPath = "http://vbef9arg13uu.guyubao.com/activity";//支付回调网关地址 private String callbackPath = "https://online.daowepark.com:443/activity";//支付回调网关地址 // private String callbackPath = "http://vbef9arg13uu.guyubao.com/activity";//支付回调网关地址 private String app_cert_path = "C:/cert/alipay/user/app_cert_path.crt";//应用公钥证书路径 @@ -70,8 +71,8 @@ private String alipay_root_cert_path = "C:/cert/alipay/user/alipay_root_cert_path.crt";//支付宝CA根证书文件路径 // private String certPath = "/usr/playpai/cert/weixin/apiclient_cert.p12";//微信证书 private String certPath = "D:/apiclient_cert.p12";//微信证书 private String certPath = "/usr/playpai/cert/weixin/apiclient_cert.p12";//微信证书 // private String certPath = "D:/apiclient_cert.p12";//微信证书 public ResultUtil confirm(String smid,String code, String outTradeNo, String amount) { AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", @@ -407,6 +408,7 @@ Map<String, Object> map = new HashMap<>(); map.put("appid", appid); map.put("mch_id", mchId); map.put("sub_mch_id", "123456"); map.put("nonce_str", nonce_str); String temp = ""; if (body.split("-").length>1){ cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WXPayConstants.java
New file @@ -0,0 +1,32 @@ package com.dsh.activity.util.wx; /** * 常量 */ public class WXPayConstants { public static final String DOMAIN_API = "https://api.mch.weixin.qq.com"; //app下单 public static final String PAY_TRANSACTIONS_APP = "/v3/pay/partner/transactions/app"; // public static final String PAY_TRANSACTIONS_APP = "/v3/pay/transactions/app"; //微信支付回调 public static final String WECHAT_PAY_NOTIFY_URL = "https://xxx.xxxx.com/deal/api/appPayment/weChatPayNotify"; //申请退款 public static final String REFUND_DOMESTIC_REFUNDS = "/refund/domestic/refunds"; //微信退款回调 public static final String WECHAT_REFUNDS_NOTIFY_URL = "https://xxx.xxxx.com/api/appPayment/weChatPayRefundsNotify"; //关闭订单 public static final String PAY_TRANSACTIONS_OUT_TRADE_NO = "/pay/transactions/out-trade-no/{}/close"; } cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WXPaySignatureCertificateUtil.java
New file @@ -0,0 +1,298 @@ package com.dsh.activity.util.wx; import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier; import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; import lombok.SneakyThrows; import org.apache.http.impl.client.CloseableHttpClient; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; /** * 微信支付V3 API 签名验证工具类 */ public class WXPaySignatureCertificateUtil { // 保存微信平台证书 private static final ConcurrentHashMap<String, AutoUpdateCertificatesVerifier> verifierMap = new ConcurrentHashMap<>(); // 缓存公钥,避免频繁IO操作 private static PublicKey cachedPublicKey = null; // 缓存私钥,避免频繁IO操作 private static PrivateKey cachedPrivateKey = null; /** * 获取HTTP客户端,用于微信支付API请求 */ public static CloseableHttpClient getWechatPayClient() throws IOException { PrivateKey merchantPrivateKey = getPrivateKey(); // 构建支付客户端 return WechatPayHttpClientBuilder.create() .withMerchant(WxV3PayConfig.Mch_ID, WxV3PayConfig.mchSerialNo, merchantPrivateKey) .withValidator(new WechatPay2Validator(getVerifier())) .build(); } /** * 获取自动更新的证书验证器 */ public static AutoUpdateCertificatesVerifier getVerifier() { String mchSerialNo = WxV3PayConfig.mchSerialNo; AutoUpdateCertificatesVerifier verifier = verifierMap.get(mchSerialNo); if (verifier == null) { synchronized (WXPaySignatureCertificateUtil.class) { verifier = verifierMap.get(mchSerialNo); if (verifier == null) { try { PrivateKey privateKey = getPrivateKey(); PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey); WechatPay2Credentials credentials = new WechatPay2Credentials(WxV3PayConfig.Mch_ID, signer); verifier = new AutoUpdateCertificatesVerifier( credentials, WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8)); verifierMap.put(mchSerialNo, verifier); } catch (Exception e) { throw new RuntimeException("初始化证书验证器失败", e); } } } } return verifier; } /** * 使用商户私钥对数据进行签名 * * @param message 待签名数据 * @return Base64编码的签名结果 */ public static String sign(String message) { try { PrivateKey privateKey = getPrivateKey(); Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(message.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(signature.sign()); } catch (Exception e) { throw new RuntimeException("签名失败", e); } } /** * 使用微信支付平台公钥验证签名 * * @param message 原始消息 * @param signature Base64编码的签名 * @return 验证结果 */ public static boolean verifySign(String message, String signature) { try { PublicKey publicKey = getWechatPublicKey(); Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(publicKey); sig.update(message.getBytes(StandardCharsets.UTF_8)); return sig.verify(Base64.getDecoder().decode(signature)); } catch (Exception e) { throw new RuntimeException("验签失败", e); } } /** * 验证微信支付通知消息的签名 * * @param request HTTP请求 * @param body 请求体内容 * @return 验证结果 */ public static boolean verifyNotify(HttpServletRequest request, String body) { try { // 获取必要的HTTP头信息 String timestamp = request.getHeader("Wechatpay-Timestamp"); String nonce = request.getHeader("Wechatpay-Nonce"); String serialNo = request.getHeader("Wechatpay-Serial"); String signature = request.getHeader("Wechatpay-Signature"); // 拼接验签字符串 String message = Stream.of(timestamp, nonce, body) .collect(Collectors.joining("\n", "", "\n")); // 使用自动更新的证书验证器进行验证 return getVerifier().verify(serialNo, message.getBytes(StandardCharsets.UTF_8), signature); } catch (Exception e) { throw new RuntimeException("验证微信支付通知签名失败", e); } } /** * APP支付签名 */ public static String appPaySign(String timestamp, String nonceStr, String prepayId) { String message = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, prepayId) .collect(Collectors.joining("\n", "", "\n")); return sign(message); } /** * JSAPI支付签名 */ public static String jsApiPaySign(String timestamp, String nonceStr, String prepayId) { String message = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, "prepay_id="+prepayId) .collect(Collectors.joining("\n", "", "\n")); return sign(message); } /** * 构建App支付参数 */ public static Map<String, String> buildAppPayParams(String prepayId) { try { String timestamp = String.valueOf(System.currentTimeMillis() / 1000); String nonceStr = generateNonceStr(); String sign = appPaySign(timestamp, nonceStr, prepayId); Map<String, String> params = new HashMap<>(); params.put("appid", WxV3PayConfig.APP_ID); params.put("partnerid", WxV3PayConfig.Mch_ID); params.put("prepayid", prepayId); params.put("package", "Sign=WXPay"); params.put("noncestr", nonceStr); params.put("timestamp", timestamp); params.put("sign", sign); return params; } catch (Exception e) { throw new RuntimeException("构建App支付参数失败", e); } } /** * 构建JSAPI支付参数 */ public static Map<String, String> buildJsApiPayParams(String prepayId) { try { String timestamp = String.valueOf(System.currentTimeMillis() / 1000); String nonceStr = generateNonceStr(); String sign = jsApiPaySign(timestamp, nonceStr, prepayId); Map<String, String> params = new HashMap<>(); params.put("appId", WxV3PayConfig.APP_ID); params.put("timeStamp", timestamp); params.put("nonceStr", nonceStr); params.put("package", "prepay_id=" + prepayId); params.put("signType", "RSA"); params.put("paySign", sign); return params; } catch (Exception e) { throw new RuntimeException("构建JSAPI支付参数失败", e); } } /** * 生成随机字符串 */ private static String generateNonceStr() { return java.util.UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32); } /** * 获取商户私钥 */ public static PrivateKey getPrivateKey() { if (cachedPrivateKey != null) { return cachedPrivateKey; } try { String filePath = "D:\\玩湃v3参数\\apiclient_key.pem"; String content = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8); String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s+", ""); KeyFactory kf = KeyFactory.getInstance("RSA"); cachedPrivateKey = kf.generatePrivate( new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); return cachedPrivateKey; } catch (IOException e) { throw new RuntimeException("读取私钥文件失败", e); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持RSA", e); } catch (InvalidKeySpecException e) { throw new RuntimeException("无效的密钥格式", e); } } /** * 获取微信支付平台公钥 */ public static PublicKey getWechatPublicKey() { if (cachedPublicKey != null) { return cachedPublicKey; } try { // 使用验证器获取最新的证书 X509Certificate certificate = getVerifier().getValidCertificate(); cachedPublicKey = certificate.getPublicKey(); return cachedPublicKey; } catch (Exception e) { throw new RuntimeException("获取微信平台公钥失败", e); } } /** * 从PEM格式文件加载公钥 */ public static PublicKey loadPublicKeyFromFile(String filePath) { try { String content = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8); String publicKeyPEM = content .replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s+", ""); byte[] encoded = Base64.getDecoder().decode(publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(new X509EncodedKeySpec(encoded)); } catch (Exception e) { throw new RuntimeException("加载公钥文件失败", e); } } /** * 从证书文件加载公钥 */ public static PublicKey loadPublicKeyFromCert(String filePath) { try (FileInputStream inputStream = new FileInputStream(filePath)) { CertificateFactory factory = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) factory.generateCertificate(inputStream); return cert.getPublicKey(); } catch (Exception e) { throw new RuntimeException("加载证书文件失败", e); } } } cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WeChatPaymentServiceImpl.java
New file @@ -0,0 +1,315 @@ //package com.dsh.activity.util.wx;/* //* //*改了七八遍 照顾找包困难的朋友吧 //* //*/ //import cn.hutool.core.text.StrFormatter; //import com.alibaba.fastjson.JSONObject; //import com.fasterxml.jackson.databind.ObjectMapper; //import com.fasterxml.jackson.databind.node.ObjectNode; //import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; //import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; //import com.wechat.pay.contrib.apache.httpclient.notification.Notification; //import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler; //import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; //import org.apache.commons.lang3.RandomStringUtils; //import org.apache.http.client.methods.CloseableHttpResponse; //import org.apache.http.client.methods.HttpPost; //import org.apache.http.entity.StringEntity; //import org.apache.http.impl.client.CloseableHttpClient; //import org.apache.http.util.EntityUtils; //import org.springframework.stereotype.Service; // //import javax.servlet.http.HttpServletRequest; //import javax.servlet.http.HttpServletResponse; //import java.io.BufferedReader; //import java.io.ByteArrayOutputStream; //import java.math.BigDecimal; //import java.nio.charset.StandardCharsets; //import java.util.HashMap; //import java.util.Map; // //@Service //public class WeChatPaymentServiceImpl implements WechatPaymentService { // // // // /** // * V3微信支付统一下单 // * // * @return // * // */ // @Override // public Map<String, Object>weChatDoUnifiedOrder() { // Map<String,Object> map =new HashMap<>(); // //支付总金额 // BigDecimal totalPrice = BigDecimal.ZERO; // totalPrice = totalPrice.add(BigDecimal.valueOf(600)); // //转换金额保留两位小数点 // Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue(); // try { // CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign(); // // //app下单 // HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.PAY_TRANSACTIONS_APP); // httpPost.addHeader("Accept", "application/json"); // httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // ByteArrayOutputStream bos = new ByteArrayOutputStream(); // ObjectMapper objectMapper = new ObjectMapper(); // ObjectNode rootNode = objectMapper.createObjectNode(); // rootNode.put("mchid", "商户id") // .put("appid", "APPID") // .put("description","描述") // .put("notify_url", WXPayConstants.WECHAT_PAY_NOTIFY_URL)//回调 // .put("out_trade_no", "订单号"); // rootNode.putObject("amount") // .put("total","总金额"); // objectMapper.writeValue(bos, rootNode); // httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8")); // //完成签名并执行请求 // CloseableHttpResponse response = httpClient.execute(httpPost); // //获取返回状态 // int statusCode = response.getStatusLine().getStatusCode(); // if (statusCode == 200) { //处理成功 // String result = EntityUtils.toString(response.getEntity(), "UTF-8"); // JSONObject object = JSONObject.parseObject(result); // //获取预付单 // String prepayId = object.getString("prepay_id"); // //生成签名 // Long timestamp = System.currentTimeMillis() / 1000; // //随机字符串 这个是微信支付maven自带的 也可以用其它的 // //这个是v2支付依赖自带的工具包 可以去掉了 // //String nonceStr = WXPayUtil.generateNonceStr(); // //该方法org.apache.commons.lang3.RandomStringUtils依赖自带随机生成字符串 RandomStringUtils.randomAlphanumeric(32) 代表生成32位 // String nonceStr = RandomStringUtils.randomAlphanumeric(32); // //生成带签名支付信息 // String paySign = WXPaySignatureCertificateUtil.appPaySign(String.valueOf(timestamp), nonceStr, prepayId); // Map<String, String> param = new HashMap<>(); // param.put("appid", WxV3PayConfig.APP_ID); // param.put("partnerid", WxV3PayConfig.Mch_ID); // param.put("prepayid", prepayId); // param.put("package", "Sign=WXPay"); // param.put("noncestr", nonceStr); // param.put("timestamp", String.valueOf(timestamp)); // param.put("sign", paySign); // map.put("code",200); // map.put("message", "下单成功"); // map.put("data", param); // return map; // } // map.put("code",200); // map.put("message", "下单失败"); // map.put("data", response); // return map; // } catch (Exception e) { // e.printStackTrace(); // } // return null; // } // // // /** // * 微信支付回调通知 // * @return // */ // @Override // public Map<String, Object> weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response){ // Map<String,Object> map = new HashMap<>(); // try { // BufferedReader br = request.getReader(); // String str = null; // StringBuilder sb = new StringBuilder(); // while ((str = br.readLine())!=null) { // sb.append(str); // } // // 构建request,传入必要参数 // NotificationRequest requests = new NotificationRequest.Builder() // .withSerialNumber(request.getHeader("Wechatpay-Serial")) // .withNonce(request.getHeader("Wechatpay-Nonce")) // .withTimestamp(request.getHeader("Wechatpay-Timestamp")) // .withSignature(request.getHeader("Wechatpay-Signature")) // .withBody(String.valueOf(sb)) // .build(); // //验签 // NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8)); // //解析请求体 // Notification notification = handler.parse(requests); // String decryptData = notification.getDecryptData(); // //解析 // JSONObject jsonObject = JSONObject.parseObject(decryptData); // //支付状态交易状态,枚举值: SUCCESS:支付成功 REFUND:转入退款 NOTPAY:未支付 CLOSED:已关闭 REVOKED:已撤销(付款码支付) // // USERPAYING:用户支付中(付款码支付) PAYERROR:支付失败(其他原因,如银行返回失败) // String trade_state = String.valueOf(jsonObject.get("trade_state")); // if (trade_state.equals("SUCCESS")) { // //订单号 // String orderNumber = String.valueOf(jsonObject.get("out_trade_no")); // //微信支付微信生成的订单号 // String transactionId = String.valueOf(jsonObject.get("transaction_id")); // //省略查询订单 // //此处处理业务 // map.put("code","SUCCESS"); // map.put("message","成功"); // //消息推送成功 // return map; // } // map.put("code","RESOURCE_NOT_EXISTS"); // map.put("message", "订单不存在"); // return map; // }catch (Exception e) { // e.printStackTrace(); // } // map.put("code","FAIL"); // map.put("message", "失败"); // return map; // } ///** // * 关闭订单 // * @param outTradeNo 订单号 // * @return // */ // @Override // public Map<String, Object> closeOrder(String outTradeNo) { // Map<String,Object> map = new HashMap<>(); // try { // //验证证书 // CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign(); // //关闭订单 // String url = StrFormatter.format(WXPayConstants.DOMAIN_API+WXPayConstants.PAY_TRANSACTIONS_OUT_TRADE_NO, outTradeNo); // HttpPost httpPost = new HttpPost(url); // httpPost.addHeader("Accept", "application/json"); // httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // ByteArrayOutputStream bos = new ByteArrayOutputStream(); // //2.添加商户id // ObjectMapper objectMapper = new ObjectMapper(); // ObjectNode rootNode = objectMapper.createObjectNode(); // rootNode.put("mchid", WxV3PayConfig.Mch_ID); // objectMapper.writeValue(bos, rootNode); // //3.调起微信关单接口 // httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8")); // //完成签名并执行请求 // CloseableHttpResponse response = httpClient.execute(httpPost); // System.out.println(response.getStatusLine().getStatusCode() == 204); // //无数据(Http状态码为204) 微信返回结果无数据 状态码为204 成功 // if (response.getStatusLine().getStatusCode() == 204) { // // //code 退款码请前往微信支付文档查询 // map.put("code",200); // map.put("message", "关闭订单成功!"); // return map; // } // } catch (Exception e) { // } // return null; // } // // /** // * 微信退款 // * @param outTradeNo 订单号 // * @return // */ // @Override // public Map<String, Object> weChatRefunds(String outTradeNo) { // Map<String,Object> map = new HashMap<>(); // //退款总金额 // BigDecimal totalPrice = BigDecimal.ZERO; // totalPrice = totalPrice.add(BigDecimal.valueOf(600)); // //转换金额 // Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue(); // // try { // //验证证书 // CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign(); // //申请退款接口 // HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.REFUND_DOMESTIC_REFUNDS); // httpPost.addHeader("Accept", "application/json"); // httpPost.addHeader("Content-type","application/json; charset=utf-8"); // ByteArrayOutputStream bos = new ByteArrayOutputStream(); // ObjectMapper objectMapper = new ObjectMapper(); // ObjectNode rootNode = objectMapper.createObjectNode(); // //微信支付订单号 // rootNode.put("transaction_id", "微信支付订单号") // //退款订单号 // .put("out_refund_no","生成退款订单号") // .put("notify_url","退款回调"); // //退款金额 // rootNode.putObject("amount") // .put("refund", "100.00") // //原订单金额 // .put("total", "100.00") // .put("currency","CNY"); // objectMapper.writeValue(bos, rootNode); // httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8")); // CloseableHttpResponse response = httpClient.execute(httpPost); // //退款成功返回消息 // String bodyAsString = EntityUtils.toString(response.getEntity()); // JSONObject jsonObject = JSONObject.parseObject(bodyAsString); // if (jsonObject.get("status").equals("SUCCESS") || jsonObject.get("status").equals("PROCESSING")) { // //code返回 // map.put("code",200); // map.put("message", "退款成功"); // return map; // } // }catch (Exception e) { // e.printStackTrace(); // } // map.put("code",500); // map.put("message", "申请退款失败!"); //// map.put("data", jsonObject); // return map; // } // // /** // * 申请退款回调 // * @param request // * @return // */ // @Override // public Map<String,Object> weChatPayRefundsNotify(HttpServletRequest request) { // Map<String,Object> map = new HashMap<>(); // try { // BufferedReader br = request.getReader(); // String str = null; // StringBuilder sb = new StringBuilder(); // while ((str = br.readLine())!=null) { // sb.append(str); // } // // 构建request,传入必要参数 // NotificationRequest requests = new NotificationRequest.Builder() // .withSerialNumber(request.getHeader("Wechatpay-Serial")) // .withNonce(request.getHeader("Wechatpay-Nonce")) // .withTimestamp(request.getHeader("Wechatpay-Timestamp")) // .withSignature(request.getHeader("Wechatpay-Signature")) // .withBody(String.valueOf(sb)) // .build(); // //验签 // NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8)); // //解析请求体 // Notification notification = handler.parse(requests); // String decryptData = notification.getDecryptData(); // //解析 // JSONObject jsonObject = JSONObject.parseObject(decryptData); // String refund_status = String.valueOf(jsonObject.get("refund_status")); // if (refund_status.equals("SUCCESS")) { // //订单号 // String orderNumber = String.valueOf(jsonObject.get("out_trade_no")); // //微信支付订单号 // String transactionId = String.valueOf(jsonObject.get("transaction_id")); // // //这里是处理业务逻辑 // // // //code 退款码请前往微信支付文档查询 // map.put("code","RESOURCE_NOT_EXISTS"); // map.put("message", "订单不存在"); // return map; // } // }catch (Exception e) { // e.printStackTrace(); // } // map.put("code","USER_ACCOUNT_ABNORMAL"); // map.put("message", "退款请求失败"); // return map; // } // //} cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WechatPaymentService.java
New file @@ -0,0 +1,56 @@ //package com.dsh.activity.util.wx; // //import javax.servlet.http.HttpServletRequest; //import javax.servlet.http.HttpServletResponse; //import java.util.Map; // ///** // * @author 影子 // */ //public interface WechatPaymentService //{ // // // /** // * 微信商品支付 // * @return // */ // public Map<String, Object> weChatDoUnifiedOrder() throws Exception; // // // // //// /** //// * 微信支付回调通知 //// * @param //// * @return //// */ //// public Map<String, Object> weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response); //// //// /** //// *微信关闭订单 //// * @param outTradeNo //// * @return //// */ //// public Map<String, Object> closeOrder(String outTradeNo); //// //// //// //// //// /** //// * 申请退款 //// * @param //// * @return //// */ //// public Map<String, Object> weChatPayRefundsNotify(HttpServletRequest request); //// //// //// //// //// /** //// * 微信退款 //// * @param outTradeNo 订单号 //// * @return //// */ //// public Map<String, Object> weChatRefunds(String outTradeNo); //} cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WxAppPayService.java
New file @@ -0,0 +1,221 @@ package com.dsh.activity.util.wx; import com.dsh.activity.util.wx.WXPayConstants; import com.dsh.activity.util.wx.WXPaySignatureCertificateUtil; import com.dsh.activity.util.wx.WxV3PayConfig; import com.fasterxml.jackson.databind.JsonNode; // 引入Jackson库处理JSON import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @Service public class WxAppPayService { private static final Logger log = LoggerFactory.getLogger(WxAppPayService.class); private final ObjectMapper objectMapper; // 用于JSON序列化和反序列化 private final CloseableHttpClient wechatPayClient; // 注入通过工具类创建的HTTP客户端 @Autowired public WxAppPayService(ObjectMapper objectMapper) throws IOException { this.objectMapper = objectMapper; // 在构造函数中初始化带有签名验证功能的HTTP客户端 this.wechatPayClient = WXPaySignatureCertificateUtil.getWechatPayClient(); log.info("微信支付V3 HTTP客户端初始化完成。"); } /** * 创建APP支付预付单 (统一下单) * * @param description 商品描述 * @param outTradeNo 商户订单号 (要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一) * @param totalAmount 支付总金额 (单位:元) * @return 用于调起APP支付的参数 Map (appid, partnerid, prepayid, package, noncestr, timestamp, sign) * @throws IOException 网络或IO异常 * @throws RuntimeException 支付请求失败或处理异常 */ public Map<String, String> createOrder(String description, String outTradeNo, BigDecimal totalAmount) throws IOException { // 1. 构建请求URL String url = WXPayConstants.DOMAIN_API + WXPayConstants.PAY_TRANSACTIONS_APP; HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // 2. 构建请求体 JSON ObjectNode rootNode = objectMapper.createObjectNode(); // rootNode.put("appid", WxV3PayConfig.APP_ID);//服务商不需要该字段 // rootNode.put("mchid", WxV3PayConfig.Mch_ID);//服务商不需要该字段 rootNode.put("description", description); rootNode.put("out_trade_no", outTradeNo); rootNode.put("notify_url", WXPayConstants.WECHAT_PAY_NOTIFY_URL); // 使用常量中的回调地址 ObjectNode amountNode = objectMapper.createObjectNode(); // 微信支付金额单位为分,需要转换 amountNode.put("total", totalAmount.multiply(new BigDecimal("100")).intValue()); amountNode.put("currency", "CNY"); // 货币类型,默认人民币 rootNode.set("amount", amountNode); // 如果你是服务商模式,需要添加子商户信息 rootNode.put("sp_mchid", WxV3PayConfig.Mch_ID); rootNode.put("sub_mchid", "123"); rootNode.put("sp_appid", "wx41d32f362ba0f911"); // rootNode.put("sub_appid", "子商户AppID"); // 如果子商户需要用自己的AppID拉起支付 String requestBody = rootNode.toString(); log.info("微信APP支付下单请求体: {}", requestBody); httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); // 3. 发送请求 try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { int statusCode = response.getStatusLine().getStatusCode(); String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.info("微信APP支付下单响应状态码: {}, 响应体: {}", statusCode, responseBody); if (statusCode == 200) { // HTTP状态码 200 表示成功 JsonNode responseNode = objectMapper.readTree(responseBody); String prepayId = responseNode.get("prepay_id").asText(); log.info("成功获取预支付交易会话标识 (prepay_id): {}", prepayId); // 4. 生成调起支付所需的参数 Map<String, String> payParams = WXPaySignatureCertificateUtil.buildAppPayParams(prepayId); log.info("生成APP支付参数: {}", payParams); return payParams; } else { // 处理错误情况 log.error("微信APP支付下单失败,状态码: {}, 响应: {}", statusCode, responseBody); // 可以根据 responseBody 中的 code 和 message 进一步分析错误 throw new RuntimeException("微信APP支付下单失败: " + responseBody); } } catch (Exception e) { log.error("微信APP支付下单请求执行异常", e); throw new IOException("微信APP支付下单请求执行异常", e); } } /** * 关闭订单 (根据商户订单号) * * @param outTradeNo 商户订单号 * @return true 如果关闭成功或订单已关闭/不存在 (根据微信文档,成功是204 No Content) * @throws IOException 网络或IO异常 * @throws RuntimeException 关闭请求失败或处理异常 */ public boolean closeOrder(String outTradeNo) throws IOException { // 1. 构建请求URL, 注意替换占位符 String url = WXPayConstants.DOMAIN_API + WXPayConstants.PAY_TRANSACTIONS_OUT_TRADE_NO.replace("{}", outTradeNo); HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // 2. 构建请求体 JSON (只需要商户号) ObjectNode rootNode = objectMapper.createObjectNode(); rootNode.put("mchid", WxV3PayConfig.Mch_ID); // 如果是服务商模式,则用 sp_mchid rootNode.put("sp_mchid", WxV3PayConfig.Mch_ID); String requestBody = rootNode.toString(); log.info("微信关单请求 URL: {}, 请求体: {}", url, requestBody); httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); // 3. 发送请求 try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { int statusCode = response.getStatusLine().getStatusCode(); // 关单成功时,微信返回 HTTP 状态码 204 No Content log.info("微信关单响应状态码: {}", statusCode); if (statusCode == 204) { log.info("订单 {} 关闭成功。", outTradeNo); return true; } else { String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.error("微信关单失败,商户订单号: {}, 状态码: {}, 响应: {}", outTradeNo, statusCode, responseBody); // 根据需要可以解析responseBody获取错误详情 return false; // 或者抛出异常,根据业务决定 } } catch (Exception e) { log.error("微信关单请求执行异常, 商户订单号: {}", outTradeNo, e); throw new IOException("微信关单请求执行异常", e); } } // --- 退款相关方法 (可选) --- /** * 申请退款 * * @param outTradeNo 原商户订单号 * @param outRefundNo 商户退款单号 (商户系统内部的退款单号,要求唯一) * @param reason 退款原因 (可选) * @param refundAmount 退款金额 (单位:元) * @param totalAmount 原订单总金额 (单位:元) * @return 退款处理结果,可以返回微信返回的JSON节点或自定义对象 * @throws IOException 网络或IO异常 * @throws RuntimeException 退款请求失败或处理异常 */ public JsonNode createRefund(String outTradeNo, String outRefundNo, String reason, BigDecimal refundAmount, BigDecimal totalAmount) throws IOException { String url = WXPayConstants.DOMAIN_API + WXPayConstants.REFUND_DOMESTIC_REFUNDS; HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); ObjectNode rootNode = objectMapper.createObjectNode(); // 如果是服务商模式,需要添加子商户号 // rootNode.put("sub_mchid", "子商户号"); rootNode.put("out_trade_no", outTradeNo); rootNode.put("out_refund_no", outRefundNo); if (reason != null && !reason.isEmpty()) { rootNode.put("reason", reason); } // 设置退款回调地址 rootNode.put("notify_url", WXPayConstants.WECHAT_REFUNDS_NOTIFY_URL); ObjectNode amountNode = objectMapper.createObjectNode(); amountNode.put("refund", refundAmount.multiply(new BigDecimal("100")).intValue()); // 退款金额,分 amountNode.put("total", totalAmount.multiply(new BigDecimal("100")).intValue()); // 原订单金额,分 amountNode.put("currency", "CNY"); rootNode.set("amount", amountNode); String requestBody = rootNode.toString(); log.info("微信申请退款请求体: {}", requestBody); httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { int statusCode = response.getStatusLine().getStatusCode(); String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.info("微信申请退款响应状态码: {}, 响应体: {}", statusCode, responseBody); if (statusCode == 200) { // 成功受理 log.info("微信退款申请成功受理。"); return objectMapper.readTree(responseBody); } else { log.error("微信申请退款失败,状态码: {}, 响应: {}", statusCode, responseBody); throw new RuntimeException("微信申请退款失败: " + responseBody); } } catch (Exception e) { log.error("微信申请退款请求执行异常", e); throw new IOException("微信申请退款请求执行异常", e); } } } cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WxPayAesUtil.java
New file @@ -0,0 +1,57 @@ package com.dsh.activity.util.wx; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; /** * 微信支付V3 AES解密工具类 (AEAD_AES_256_GCM) */ public class WxPayAesUtil { private static final String ALGORITHM = "AES/GCM/NoPadding"; private static final int TAG_LENGTH_BIT = 128; // GCM认证标签长度,固定为128位 private static final int NONCE_LENGTH_BYTE = 12; // GCM随机串长度,固定为12字节 private static final String TRANSFORMATION = "AES/GCM/NoPadding"; // 算法/模式/填充 /** * 解密微信支付回调通知中的加密信息 * * @param apiV3Key APIv3密钥 (来自 WxV3PayConfig) * @param associatedData 附加数据 (resource.associated_data) * @param nonce 随机串 (resource.nonce) * @param ciphertext 密文 (resource.ciphertext),Base64编码 * @return 解密后的明文字符串 * @throws GeneralSecurityException 解密失败时抛出异常 */ public static String decrypt(String apiV3Key, String associatedData, String nonce, String ciphertext) throws GeneralSecurityException { try { SecretKeySpec key = new SecretKeySpec(apiV3Key.getBytes(StandardCharsets.UTF_8), "AES"); GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce.getBytes(StandardCharsets.UTF_8)); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, key, spec); cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8)); // 设置附加认证数据 byte[] decodedCiphertext = Base64.getDecoder().decode(ciphertext); byte[] decryptedBytes = cipher.doFinal(decodedCiphertext); return new String(decryptedBytes, StandardCharsets.UTF_8); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new IllegalStateException("当前JDK环境不支持AEAD_AES_256_GCM", e); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { throw new IllegalArgumentException("无效的密钥或GCM参数", e); } catch (Exception e) { // 包括 BadPaddingException 等解密失败的情况 throw new GeneralSecurityException("AES/GCM 解密失败", e); } } } cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WxPayNotifyController.java
New file @@ -0,0 +1,177 @@ package com.dsh.activity.util.wx; import com.dsh.activity.util.wx.WXPaySignatureCertificateUtil; import com.dsh.activity.util.wx.WxPayAesUtil; import com.dsh.activity.util.wx.WxV3PayConfig; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/api/appPayment") // 路径前缀,与常量中配置的回调URL匹配 public class WxPayNotifyController { private static final Logger log = LoggerFactory.getLogger(WxPayNotifyController.class); private final ObjectMapper objectMapper; @Autowired public WxPayNotifyController(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } /** * 接收微信支付结果通知 * URL需要与 WXPayConstants.WECHAT_PAY_NOTIFY_URL 匹配 */ @PostMapping("/weChatPayNotify") public ResponseEntity<Map<String, String>> handleWeChatPayNotify(HttpServletRequest request, @RequestBody String requestBody) { Map<String, String> responseMap = new HashMap<>(); try { // 1. 验证签名 (使用工具类,它会处理证书) boolean verifyResult = WXPaySignatureCertificateUtil.verifyNotify(request, requestBody); if (!verifyResult) { log.error("微信支付通知验签失败!"); responseMap.put("code", "FAIL"); responseMap.put("message", "验签失败"); return new ResponseEntity<>(responseMap, HttpStatus.BAD_REQUEST); // 返回错误状态码 } log.info("微信支付通知验签成功。"); // 2. 解析通知体 JsonNode notifyData = objectMapper.readTree(requestBody); String eventType = notifyData.get("event_type").asText(); // 只处理支付成功的通知类型 if ("TRANSACTION.SUCCESS".equals(eventType)) { log.info("处理支付成功通知..."); JsonNode resourceNode = notifyData.get("resource"); String associatedData = resourceNode.get("associated_data").asText(); String nonce = resourceNode.get("nonce").asText(); String ciphertext = resourceNode.get("ciphertext").asText(); // 3. 解密关键信息 String decryptedDataJson = WxPayAesUtil.decrypt(WxV3PayConfig.apiV3Key, associatedData, nonce, ciphertext); log.info("解密后的支付通知信息: {}", decryptedDataJson); JsonNode decryptedData = objectMapper.readTree(decryptedDataJson); // 4. 处理业务逻辑 String outTradeNo = decryptedData.get("out_trade_no").asText(); String transactionId = decryptedData.get("transaction_id").asText(); String tradeState = decryptedData.get("trade_state").asText(); // ... 获取其他需要的信息,例如支付金额、用户openid等 // TODO: 在这里实现你的业务逻辑: // 1. 根据 outTradeNo 查询你的数据库订单状态。 // 2. 判断订单是否已经处理过(防止重复处理通知)。 // 3. 如果订单未处理且 tradeState 为 SUCCESS,则更新订单状态为支付成功。 // 4. 记录 transactionId (微信支付订单号)。 // 5. 执行后续业务流程(如发货、增加积分等)。 // 6. 如果处理失败,可以考虑记录日志并后续重试,但仍需返回成功给微信,避免微信重复通知。 log.info("业务逻辑处理完成,商户订单号: {}, 微信订单号: {}", outTradeNo, transactionId); } else { log.warn("收到非支付成功类型的通知: {}", eventType); // 其他类型的通知,根据需要处理或忽略 } // 5. 返回成功响应给微信平台 responseMap.put("code", "SUCCESS"); responseMap.put("message", "成功"); return new ResponseEntity<>(responseMap, HttpStatus.OK); } catch (Exception e) { log.error("处理微信支付通知异常", e); responseMap.put("code", "FAIL"); responseMap.put("message", "处理失败"); // 即使处理失败,也尽量返回成功给微信,避免重复通知轰炸,然后在后台处理异常。 // 但如果验签失败,可以返回错误状态码。 return new ResponseEntity<>(responseMap, HttpStatus.INTERNAL_SERVER_ERROR); // 或者返回OK,根据策略定 } } /** * 接收微信退款结果通知 * URL需要与 WXPayConstants.WECHAT_REFUNDS_NOTIFY_URL 匹配 */ @PostMapping("/weChatPayRefundsNotify") public ResponseEntity<Map<String, String>> handleWeChatRefundsNotify(HttpServletRequest request, @RequestBody String requestBody) { Map<String, String> responseMap = new HashMap<>(); try { // 1. 验证签名 boolean verifyResult = WXPaySignatureCertificateUtil.verifyNotify(request, requestBody); if (!verifyResult) { log.error("微信退款通知验签失败!"); responseMap.put("code", "FAIL"); responseMap.put("message", "验签失败"); return new ResponseEntity<>(responseMap, HttpStatus.BAD_REQUEST); } log.info("微信退款通知验签成功。"); // 2. 解析通知体 JsonNode notifyData = objectMapper.readTree(requestBody); String eventType = notifyData.get("event_type").asText(); // 处理退款成功或异常的通知 if ("REFUND.SUCCESS".equals(eventType) || "REFUND.ABNORMAL".equals(eventType) || "REFUND.CLOSED".equals(eventType)) { log.info("处理退款通知,类型: {}", eventType); JsonNode resourceNode = notifyData.get("resource"); String associatedData = resourceNode.get("associated_data").asText(); String nonce = resourceNode.get("nonce").asText(); String ciphertext = resourceNode.get("ciphertext").asText(); // 3. 解密关键信息 String decryptedDataJson = WxPayAesUtil.decrypt(WxV3PayConfig.apiV3Key, associatedData, nonce, ciphertext); log.info("解密后的退款通知信息: {}", decryptedDataJson); JsonNode decryptedData = objectMapper.readTree(decryptedDataJson); // 4. 处理业务逻辑 String outTradeNo = decryptedData.get("out_trade_no").asText(); String outRefundNo = decryptedData.get("out_refund_no").asText(); String refundStatus = decryptedData.get("refund_status").asText(); // SUCCESS, CLOSED, ABNORMAL // ... 获取其他需要的信息,例如退款金额、微信退款单号 refund_id 等 // TODO: 在这里实现你的退款业务逻辑: // 1. 根据 outRefundNo 查询你的数据库退款单状态。 // 2. 判断退款单是否已经处理过。 // 3. 根据 refundStatus 更新退款单状态。 // 4. 如果退款成功 (SUCCESS),可能需要执行一些操作,如返还库存、通知用户等。 // 5. 如果退款关闭或异常,也需要记录状态。 log.info("退款业务逻辑处理完成,商户订单号: {}, 商户退款单号: {}, 退款状态: {}", outTradeNo, outRefundNo, refundStatus); } else { log.warn("收到非退款类型的通知: {}", eventType); } // 5. 返回成功响应给微信平台 responseMap.put("code", "SUCCESS"); responseMap.put("message", "成功"); return new ResponseEntity<>(responseMap, HttpStatus.OK); } catch (Exception e) { log.error("处理微信退款通知异常", e); responseMap.put("code", "FAIL"); responseMap.put("message", "处理失败"); return new ResponseEntity<>(responseMap, HttpStatus.INTERNAL_SERVER_ERROR); } } } cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WxV3PayConfig.java
New file @@ -0,0 +1,56 @@ package com.dsh.activity.util.wx; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; // 如果需要静态访问 @Component public class WxV3PayConfig { private String appIdValue = "wx41d32f362ba0f911"; public static String APP_ID= "wx41d32f362ba0f911"; private String mchIdValue= "1681873607"; public static String Mch_ID= "1681873607"; private String apiV3KeyValue= "1skiujh28376shznxmslwosiusytersq"; public static String apiV3Key= "1skiujh28376shznxmslwosiusytersq"; private String mchSerialNoValue= "55714944F7A7E52526F708280B176DCC838F371A"; public static String mchSerialNo= "55714944F7A7E52526F708280B176DCC838F371A"; private String privateKeyPathValue= "D:\\玩湃v3参数\\1681873607_20250424_cert\\apiclient_key.pem"; public static String privateKeyPath= "D:\\玩湃v3参数\\1681873607_20250424_cert\\apiclient_key.pem"; // 如果需要静态访问,可以使用 @PostConstruct 初始化静态变量 @PostConstruct public void init() { APP_ID = this.appIdValue; Mch_ID = this.mchIdValue; apiV3Key = this.apiV3KeyValue; mchSerialNo = this.mchSerialNoValue; privateKeyPath = this.privateKeyPathValue; // WXPaySignatureCertificateUtil 会用到这个路径 // 可以在这里加一些非空检查 if (APP_ID == null || Mch_ID == null || apiV3Key == null || mchSerialNo == null || privateKeyPath == null) { System.err.println("微信支付V3配置加载不完整,请检查配置文件!"); // 在实际应用中,这里可能需要抛出异常或采取其他错误处理措施 } else { System.out.println("微信支付V3配置加载完成。"); } } // 注意: WXPaySignatureCertificateUtil 中的 getPrivateKey() 方法现在应该使用 WxV3PayConfig.privateKeyPath // 你需要稍微修改 WXPaySignatureCertificateUtil.getPrivateKey() 方法: /* public static PrivateKey getPrivateKey() { if (cachedPrivateKey != null) { return cachedPrivateKey; } try { String filePath = WxV3PayConfig.privateKeyPath; // 使用配置类中的路径 // ... rest of the method ... } // ... catch blocks ... } */ } cloud-server-activity/src/main/resources/mapper/HuiminCardMapper.xml
@@ -12,7 +12,6 @@ and t1.status = 1 order by t1.sort desc limit #{pageNo}, #{pageSize} </select> <select id="getHuiminAgreementAndListNolimit" resultType="com.dsh.activity.entity.THuiminCard"> @@ -31,6 +30,7 @@ t1.status!=1 and t1.appUserId = #{appUserId} order by t1.status asc limit #{pageNo}, #{pageSize} </select> cloud-server-activity/src/main/resources/mapper/PayHuiminMapper.xml
@@ -173,6 +173,7 @@ </when> </choose> </if> and tph.paymentTime IS NOT NULL </where> GROUP BY tph.id ORDER BY tph.insertTime DESC cloud-server-activity/src/main/resources/sharding-jdbc.properties
@@ -1,22 +1,9 @@ datasource.names=master0 datasource.master0.type=com.alibaba.druid.pool.DruidDataSource datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver datasource.master0.url=jdbc:mysql://192.168.110.80:3306/playpai_activity?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai datasource.master0.username=root datasource.master0.password=123456 datasource.master0.maxActive=20 datasource.master0.maxWait=60000 datasource.master0.minIdle=5 datasource.master0.initialSize=2 #datasource.names=master0 #datasource.master0.type=com.alibaba.druid.pool.DruidDataSource #datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver #datasource.master0.url=jdbc:mysql://127.0.0.1:3306/playpai_activity?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai #datasource.master0.url=jdbc:mysql://192.168.110.80:3306/playpai_activity?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai #datasource.master0.username=root #datasource.master0.password=playpai2023! #datasource.master0.password=123456 #datasource.master0.maxActive=20 #datasource.master0.maxWait=60000 #datasource.master0.minIdle=5 @@ -24,4 +11,17 @@ datasource.names=master0 datasource.master0.type=com.alibaba.druid.pool.DruidDataSource datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver datasource.master0.url=jdbc:mysql://127.0.0.1:3306/playpai_activity?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai datasource.master0.username=root datasource.master0.password=playpai2023! datasource.master0.maxActive=20 datasource.master0.maxWait=60000 datasource.master0.minIdle=5 datasource.master0.initialSize=2 cloud-server-communityWorldCup/src/main/resources/sharding-jdbc.properties
@@ -1,22 +1,9 @@ #datasource.names=master0 #datasource.master0.type=com.alibaba.druid.pool.DruidDataSource #datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver #datasource.master0.url=jdbc:mysql://8.137.22.229:3306/playpai_community_world_cup?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai #datasource.master0.username=root #datasource.master0.password=playpai2023! #datasource.master0.maxActive=20 #datasource.master0.maxWait=60000 #datasource.master0.minIdle=5 #datasource.master0.initialSize=2 datasource.names=master0 datasource.master0.type=com.alibaba.druid.pool.DruidDataSource datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver datasource.master0.url=jdbc:mysql://192.168.110.80:3306/playpai_community_world_cup?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai datasource.master0.url=jdbc:mysql://8.137.22.229:3306/playpai_community_world_cup?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai datasource.master0.username=root datasource.master0.password=123456 datasource.master0.password=playpai2023! datasource.master0.maxActive=20 datasource.master0.maxWait=60000 datasource.master0.minIdle=5 @@ -24,3 +11,16 @@ #datasource.names=master0 #datasource.master0.type=com.alibaba.druid.pool.DruidDataSource #datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver #datasource.master0.url=jdbc:mysql://192.168.110.80:3306/playpai_community_world_cup?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai #datasource.master0.username=root #datasource.master0.password=123456 #datasource.master0.maxActive=20 #datasource.master0.maxWait=60000 #datasource.master0.minIdle=5 #datasource.master0.initialSize=2 cloud-server-competition/src/main/java/com/dsh/competition/service/impl/ParticipantServiceImpl.java
@@ -67,6 +67,10 @@ if (null != one) { return ResultUtil.error("电话号码重复"); } // Participant two = this.getOne(new QueryWrapper<Participant>().eq("appUserId", uid).eq("idcard", addParticipant.getIdcard()).eq("state", 1)); // if (null != two) { // return ResultUtil.error("身份证号码重复"); // } if (ToolUtil.isNotEmpty(addParticipant.getName()) && ToolUtil.isNotEmpty(addParticipant.getIdcard())) { Boolean aBoolean = JuHeUtil.idcardAuthentication(addParticipant.getIdcard(), addParticipant.getName()); if (!aBoolean) { @@ -94,8 +98,8 @@ tStudent.setName(addParticipant.getName()); tStudent.setPhone(addParticipant.getPhone()); if (ToolUtil.isNotEmpty(addParticipant.getBirthday())){ Date date = DateUtils.parseDate(addParticipant.getBirthday()); tStudent.setBirthday(date); Date parse = sdf.parse(addParticipant.getBirthday()); tStudent.setBirthday(parse); }else{ String birthDateStr = addParticipant.getIdcard().substring(6, 14); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); @@ -187,7 +191,9 @@ Integer integer = coursePackagePaymentClient.queryResidueClassHour(tStudent.getId()); participantVo.setResidueClassHour(integer); participantVo.setPhone(tStudent.getPhone()); participantVo.setHeight(tStudent.getHeight().intValue()); if (tStudent.getHeight()!=null){ participantVo.setHeight(tStudent.getHeight().intValue()); } participantVo.setWeight(tStudent.getWeight()); participantVo.setHeadImg(tStudent.getHeadImg()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");