From a2757a2849066ae0e78ff6c7dc1279abd04e5e88 Mon Sep 17 00:00:00 2001 From: Administrator Date: Thu, 9 Jan 2025 11:26:09 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E8=B0=83=E6=95=B4gateway=E7=BD=91?= =?UTF-8?q?=E5=85=B3=E4=B8=AD=E5=BE=AE=E4=BF=A1=E6=9C=8D=E5=8A=A1=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E9=80=BB=E8=BE=91=202.=20=E6=8D=A2=E7=94=B5=E6=AD=A5?= =?UTF-8?q?=E9=AA=A4=E4=B8=AD=E6=B7=BB=E5=8A=A0=E6=AD=A5=E9=AA=A4=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E5=AD=97=E6=AE=B5=203.=20=E6=B7=BB=E5=8A=A0=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=85=AC=E4=BC=97=E5=8F=B7=E6=A8=A1=E7=89=88=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97=EF=BC=8C=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E9=A2=84=E7=BA=A6=E6=B6=88=E6=81=AF=204.=20=E5=B0=8F?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E4=BA=8C=E7=BB=B4=E7=A0=81=E5=85=B3=E8=81=94?= =?UTF-8?q?=E5=88=B0=E4=BA=91=E5=B9=B3=E5=8F=B0=E5=90=8E=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/entity/cloud/BatteryStationDc.java | 3 + .../entity/cloud/OrderSwapBatteryPre.java | 1 + .../entity/cloud/OrderSwapBatteryStep.java | 3 + .../common/core/entity/wechat/WechatUser.java | 6 + .../evotech/hd/common/core/enums/CodeMsg.java | 3 +- .../test/MqttMessageTestController.java | 6 +- .../message/dto/newer/state/OrderStatus.java | 1 + .../message/handle/RequestMessageService.java | 28 +-- .../message/handle/StateMessageService.java | 20 ++- .../evotech/hd/cloud/rpc/ResourceService.java | 21 +++ .../evotech/hd/cloud/rpc/WechatService.java | 14 ++ .../impl/BatteryStationDcServiceImpl.java | 2 + .../impl/BatteryStationServiceImpl.java | 2 + .../impl/OrderSwapBatteryServiceImpl.java | 14 +- .../newthread/GZHTemplateMessageService.java | 29 ++++ .../utils/components/HDStepDictComponent.java | 40 +++++ .../SwapOrderBasicFeeComponent.java | 49 ++++++ .../src/main/resources/application.yml | 5 + .../CloudManageServerApplicationTests.java | 13 ++ .../gateway/oauth2/AuthorizationManager.java | 25 ++- .../gateway/oauth2/ResourceServerConfig.java | 4 +- .../oauth2/WechatAuthorizationManager.java | 28 ++- .../exception/GlobalExceptionHandler.java | 1 - .../oauth2/exception/GlobalExceptionType.java | 4 +- .../service/impl/DictServiceImpl.java | 1 + .../hd/wechat/config/GZHProperties.java | 32 ++++ .../controller/CloudServeController.java | 9 + .../controller/XCXQRCodeController.java | 3 + .../gzh/GZHMessageReceiveController.java | 36 ++++ .../gzh/GZHMessageSendController.java | 56 ++++++ .../wechat/entity/gzh/GZHSubscribeEvent.java | 27 +++ .../hd/wechat/entity/gzh/GZHWechatSigDTO.java | 23 +++ .../templatemessage/ChargeTemplateData.java | 53 ++++++ .../MessageTemplateSendData.java | 35 ++++ .../gzh/templatemessage/Miniprogram.java | 15 ++ .../gzh/templatemessage/PayTemplateData.java | 53 ++++++ .../templatemessage/PreOrderTemplateData.java | 49 ++++++ .../gzh/templatemessage/SwapTemplateData.java | 45 +++++ .../hd/wechat/service/AccessTokenService.java | 4 +- .../hd/wechat/service/CloudService.java | 5 + .../service/gzh/GZHAccessTokenService.java | 38 ++++ .../service/gzh/GZHMessageReceiveService.java | 106 +++++++++++ .../gzh/GZHMessageTemplateService.java | 164 ++++++++++++++++++ .../wechat/utils/gzh/OpenId2UnionIdUtil.java | 27 +++ .../wechat/utils/gzh/TemplateMessageUtil.java | 30 ++++ ...itional-spring-configuration-metadata.json | 40 +++++ .../src/main/resources/application.yml | 12 ++ 47 files changed, 1132 insertions(+), 53 deletions(-) create mode 100644 cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/ResourceService.java create mode 100644 cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java create mode 100644 cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/HDStepDictComponent.java create mode 100644 cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/SwapOrderBasicFeeComponent.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageReceiveController.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHSubscribeEvent.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHWechatSigDTO.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/ChargeTemplateData.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/MessageTemplateSendData.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/Miniprogram.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PayTemplateData.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PreOrderTemplateData.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/SwapTemplateData.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHAccessTokenService.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageReceiveService.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/OpenId2UnionIdUtil.java create mode 100644 wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/TemplateMessageUtil.java diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/BatteryStationDc.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/BatteryStationDc.java index d72cca8..7d772d2 100644 --- a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/BatteryStationDc.java +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/BatteryStationDc.java @@ -36,6 +36,9 @@ public class BatteryStationDc implements Serializable { @Schema(description = "电池型号编码", requiredMode = RequiredMode.REQUIRED) @NotBlank(message = "型号编码不能为空") private String typeCode; + + @Schema(description = "电池型号名称") + private String typeName; @Schema(description = "电池编码", requiredMode = RequiredMode.REQUIRED) @NotBlank(message = "电池编码不能为空") diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryPre.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryPre.java index f751b67..9604743 100644 --- a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryPre.java +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryPre.java @@ -60,6 +60,7 @@ public class OrderSwapBatteryPre implements Serializable { private String stationName; @Schema(description = "预约时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") private Date reservationTime; diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryStep.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryStep.java index d3c84e5..f67f93c 100644 --- a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryStep.java +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/OrderSwapBatteryStep.java @@ -33,6 +33,9 @@ public class OrderSwapBatteryStep implements Serializable { @Schema(description = "步骤:1-车辆进站,2-车辆到达指定位置,3-对中机构,4-取新电,5-拆旧电,6-装新电,7-放旧电,8-完成") private Integer step; + + @Schema(description = "步骤名称") + private String stepName; @Schema(description = "步骤时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/wechat/WechatUser.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/wechat/WechatUser.java index d369d64..3047caa 100644 --- a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/wechat/WechatUser.java +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/wechat/WechatUser.java @@ -62,6 +62,12 @@ public class WechatUser implements Serializable { @Schema(description = "父账户名称") private String pname; + + @Schema(description = "公众号原始ID") + private String gzhId; + + @Schema(description = "公众号openid") + private String gzhOpenid; @Schema(description = "创建人", hidden = true) private String creater; diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/enums/CodeMsg.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/enums/CodeMsg.java index c6d3485..f52c178 100644 --- a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/enums/CodeMsg.java +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/enums/CodeMsg.java @@ -80,7 +80,8 @@ public enum CodeMsg { WECHAT_SERRION_ERROR("W0401", "小程序登录态异常"), WECHAT_API_ERROR("W0402", "小程序接口调用异常"), WECHAT_NOT_LOGIN("W0403", "用户未登陆!"), - WECHAT_TOKEN_INVALID("W0404", "无效token!"); + WECHAT_TOKEN_INVALID("W0404", "无效token!"), + WECHAT_TOKEN_EXPIRED("W0405", "token已过期!"); String code; diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/test/MqttMessageTestController.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/test/MqttMessageTestController.java index 7729547..b08cd31 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/test/MqttMessageTestController.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/test/MqttMessageTestController.java @@ -14,6 +14,7 @@ import com.evotech.hd.cloud.mqtt.enums.StateFunctionTypesEnum; import com.evotech.hd.cloud.mqtt.message.MqttMessageHeader; import com.evotech.hd.cloud.mqtt.message.dto.newer.req.order.OrderByPlateNumReq; import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatus; +import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatusData; import com.evotech.hd.cloud.mqtt.message.dto.newer.state.SwapStep; import com.evotech.hd.common.core.entity.Result; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; @@ -62,10 +63,9 @@ public class MqttMessageTestController { @Operation(summary = "反馈订单状态") @PostMapping("/orderStatus") @ApiOperationSupport(order = 2) - public Result orderStatus(@ParameterObject OrderStatus orderStatus, String stationCode) { - + public Result orderStatus(@ParameterObject OrderStatus orderStatus, @ParameterObject OrderStatusData statusData, String stationCode) { + orderStatus.setStatusData(statusData); JSONObject jo = JSONUtil.parseObj(orderStatus); - String topic = mqttTestUtil.getTopic(stationCode, MqttMessageTypeEnum.STATE.getType()); MqttMessageHeader header = mqttTestUtil.getHeader(StateFunctionTypesEnum.FUN_ORDERSTATUS.getFunction()); diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/dto/newer/state/OrderStatus.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/dto/newer/state/OrderStatus.java index 996c8e3..89c72f1 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/dto/newer/state/OrderStatus.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/dto/newer/state/OrderStatus.java @@ -21,5 +21,6 @@ public class OrderStatus { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date statusTime; + @Schema(hidden = true) private OrderStatusData statusData; } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/RequestMessageService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/RequestMessageService.java index 6f41201..975d32b 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/RequestMessageService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/RequestMessageService.java @@ -1,6 +1,5 @@ package com.evotech.hd.cloud.mqtt.message.handle; -import java.time.LocalTime; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -13,7 +12,6 @@ import org.springframework.util.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.evotech.hd.cloud.dao.BatteryStationDcDao; -import com.evotech.hd.cloud.dao.BatteryStationHdFeeStandardDao; import com.evotech.hd.cloud.dao.OrderSwapBatteryDao; import com.evotech.hd.cloud.dao.OrderSwapBatteryPreDao; import com.evotech.hd.cloud.dao.VehicleWechatUserRelationDao; @@ -30,9 +28,8 @@ import com.evotech.hd.cloud.mqtt.message.dto.newer.req.order.OrderByPlateNumResp import com.evotech.hd.cloud.mqtt.message.dto.newer.req.order.OrderData; import com.evotech.hd.cloud.service.OrderSwapBatteryService; import com.evotech.hd.cloud.utils.CommonUtil; +import com.evotech.hd.cloud.utils.components.SwapOrderBasicFeeComponent; import com.evotech.hd.common.core.entity.cloud.BatteryStationDc; -import com.evotech.hd.common.core.entity.cloud.BatteryStationHdFeeStandard; -import com.evotech.hd.common.core.entity.cloud.BatteryStationHdFeeStandardDetail; import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; import com.evotech.hd.common.core.entity.cloud.VehicleWechatUserRelation; @@ -61,7 +58,7 @@ public class RequestMessageService { @Resource private OrderSwapBatteryService orderSwapBatteryService; @Resource - private BatteryStationHdFeeStandardDao batteryStationHdFeeStandardDao; + private SwapOrderBasicFeeComponent orderBasicFeeComponent; @Async("taskExecutor") public void request(MessageTopic topic, MqttMessageHeader header, JSONObject dataBody) { @@ -134,26 +131,7 @@ public class RequestMessageService { osb.setStationCode(osbp.getStationCode()); osb.setStationName(osbp.getStationName()); // 加上费用标准 - List list = batteryStationHdFeeStandardDao.listFeeStandard(osbp.getStationCode(), DateUtil.format(d, DatePattern.PURE_DATE_FORMATTER)); - if (!list.isEmpty()) { - BatteryStationHdFeeStandard standard = list.get(0); - List detailList = standard.getDetailList(); - if (!detailList.isEmpty()) { - detailList = detailList.stream().filter(i -> i.getTimeBegin().compareTo(LocalTime.now()) <= 0) - .filter(i -> i.getTimeEnd().compareTo(LocalTime.now()) >= 0).toList(); - if (!detailList.isEmpty()) { - BatteryStationHdFeeStandardDetail detail = detailList.get(0); - osb.setBasicFee(detail.getEachKwhFee()); - osb.setServiceFee(detail.getTimeServiceFee()); - } else { - osb.setBasicFee(standard.getEachKwhFee()); - osb.setServiceFee(standard.getCommonRemainFee()); - } - } else { - osb.setBasicFee(standard.getEachKwhFee()); - osb.setServiceFee(standard.getCommonRemainFee()); - } - } + osb = orderBasicFeeComponent.orderBasicFee(osb); orderSwapBatteryService.add(osb); } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/StateMessageService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/StateMessageService.java index 41899b0..f6e2264 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/StateMessageService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/mqtt/message/handle/StateMessageService.java @@ -17,6 +17,7 @@ import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatus; import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatusData; import com.evotech.hd.cloud.mqtt.message.dto.newer.state.SwapStep; import com.evotech.hd.cloud.service.BatteryStationDcService; +import com.evotech.hd.cloud.utils.components.HDStepDictComponent; import com.evotech.hd.common.core.entity.cloud.BatteryTrace; import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; @@ -43,6 +44,8 @@ public class StateMessageService { private OrderSwapBatteryStepDao orderSwapBatteryStepDao; @Resource private BatteryStationDcService batteryStationDcService; + @Resource + private HDStepDictComponent hdStepDictComponent; @Async("taskExecutor") public void state(MessageTopic topic, MqttMessageHeader header, JSONObject dataBody) { @@ -60,6 +63,7 @@ public class StateMessageService { BeanUtils.copyProperties(swapStep, step); step.setCtime(new Date()); step.setCreater("SYS"); + step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep())); orderSwapBatteryStepDao.insert(step); break; @@ -90,6 +94,7 @@ public class StateMessageService { step.setStepTime(orderStatus.getStatusTime()); step.setCtime(new Date()); step.setCreater("SYS"); + step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep())); orderSwapBatteryStepDao.insert(step); // 添加2块电池的溯源记录 addBatteryTrace(orderStatus, statusData, osb); @@ -140,13 +145,14 @@ public class StateMessageService { // 修改订单状态 OrderSwapBattery osb = alterOrderStatus(orderStatus, null); // 添加换电步骤1-车辆进站 - OrderSwapBatteryStep osbs = new OrderSwapBatteryStep(); - osbs.setOrderNo(orderStatus.getOrderNo()); - osbs.setStep(1); - osbs.setStepTime(orderStatus.getStatusTime()); - osbs.setCtime(new Date()); - osbs.setCreater("SYS"); - orderSwapBatteryStepDao.insert(osbs); + OrderSwapBatteryStep step = new OrderSwapBatteryStep(); + step.setOrderNo(orderStatus.getOrderNo()); + step.setStep(1); + step.setStepTime(orderStatus.getStatusTime()); + step.setCtime(new Date()); + step.setCreater("SYS"); + step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep())); + orderSwapBatteryStepDao.insert(step); // 修改预约订单为完成 OrderSwapBatteryPre osbp = new OrderSwapBatteryPre(); osbp.setStatus(2); diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/ResourceService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/ResourceService.java new file mode 100644 index 0000000..10c1924 --- /dev/null +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/ResourceService.java @@ -0,0 +1,21 @@ +package com.evotech.hd.cloud.rpc; + +import java.util.List; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import com.evotech.hd.common.core.entity.Result; +import com.evotech.hd.common.core.entity.resource.dict.Dict; + +@FeignClient(value = "resource-server") +public interface ResourceService { + + + @GetMapping(value = "/resource/dict/listdict", + consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) + public Result> listDict(@RequestParam String typeCode); + +} diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/WechatService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/WechatService.java index 4b3e6c3..a162554 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/WechatService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/rpc/WechatService.java @@ -1,10 +1,16 @@ package com.evotech.hd.cloud.rpc; +import org.springdoc.core.annotations.ParameterObject; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; +import com.evotech.hd.common.core.entity.Result; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; + @FeignClient(value = "wechat-server") public interface WechatService { @@ -16,5 +22,13 @@ public interface WechatService { @GetMapping(value = "/wechat/xcx/qrcode/create2", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public String createQRCode2(@RequestParam String path, @RequestParam String width); + + @PostMapping(value = "/wechat/gzh/msg/send/preorder2", + consumes = {MediaType.APPLICATION_JSON_VALUE}) + public Result preOrderMessage(OrderSwapBatteryPre osbp); + + @PostMapping(value = "/wechat/gzh/msg/send/order", + consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) + public Result orderMessage(@ParameterObject OrderSwapBattery osb, @RequestParam Integer templateType); } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationDcServiceImpl.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationDcServiceImpl.java index 065c08b..f6985f1 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationDcServiceImpl.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationDcServiceImpl.java @@ -4,6 +4,7 @@ import java.util.Date; import java.util.List; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -29,6 +30,7 @@ public class BatteryStationDcServiceImpl implements BatteryStationDcService { private BatteryTraceDao batteryTraceDao; @Override + @Transactional public Result add(BatteryStationDc bsdc) { Date d = new Date(); bsdc.setCtime(d); diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationServiceImpl.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationServiceImpl.java index ec422fb..fc835e5 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationServiceImpl.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/BatteryStationServiceImpl.java @@ -154,6 +154,8 @@ public class BatteryStationServiceImpl implements BatteryStationService { res = res.stream().map(i -> { if (StringUtils.hasText(i.getCarTypeCode()) && i.getCarTypeCode().contains(vi.getTypeCode())) { i.setIsSuitable(true); + } else { + i.setIsSuitable(false); } return i; }) diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java index 688fd6c..fbe4904 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/OrderSwapBatteryServiceImpl.java @@ -17,6 +17,8 @@ import com.evotech.hd.cloud.dao.OrderSwapBatteryPreDao; import com.evotech.hd.cloud.dao.OrderSwapBatteryStepDao; import com.evotech.hd.cloud.dao.VehicleInfoDao; import com.evotech.hd.cloud.service.OrderSwapBatteryService; +import com.evotech.hd.cloud.service.newthread.GZHTemplateMessageService; +import com.evotech.hd.cloud.utils.components.SwapOrderBasicFeeComponent; import com.evotech.hd.common.core.dao.wechat.WechatUserDao; import com.evotech.hd.common.core.entity.Result; import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; @@ -42,6 +44,10 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService { private VehicleInfoDao vehicleInfoDao; @Resource private WechatUserDao wechatUserDao; + @Resource + private SwapOrderBasicFeeComponent orderBasicFeeComponent; + @Resource + private GZHTemplateMessageService templateMessageService; @Override @@ -72,6 +78,9 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService { osbp.setCtime(d); int n = orderSwapBatteryPreDao.insert(osbp); if (n == 1) { + // 发送服务号消息,没有消息队列,先用接口吧 + osbp.setCtime(null); + templateMessageService.preOrderMessageSend(osbp); return new Result().success(n); } return new Result().error("添加预约换电订单出错!"); @@ -189,7 +198,10 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService { } // 2. 检查数据 if (order.getBasicFee() == null || order.getServiceFee() == null) { - return new Result().error("订单费用标准异常!"); + order = orderBasicFeeComponent.orderBasicFee(order); + if (order.getBasicFee() == null || order.getServiceFee() == null) { + return new Result().error("订单费用标准异常!"); + } } // 3. 选择费用计算方式 计算费用 // 先按电量计算 diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java new file mode 100644 index 0000000..e5a749c --- /dev/null +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java @@ -0,0 +1,29 @@ +package com.evotech.hd.cloud.service.newthread; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import com.evotech.hd.cloud.rpc.WechatService; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; + +import jakarta.annotation.Resource; + +@Service +public class GZHTemplateMessageService { + + @Resource + private WechatService wechatService; + + @Async("taskExecutor") + public void preOrderMessageSend(OrderSwapBatteryPre osbp) { + wechatService.preOrderMessage(osbp); + } + + + @Async("taskExecutor") + public void orderMessageSend(OrderSwapBattery osb, Integer type) { + wechatService.orderMessage(osb, type); + } + +} diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/HDStepDictComponent.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/HDStepDictComponent.java new file mode 100644 index 0000000..a0fccec --- /dev/null +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/HDStepDictComponent.java @@ -0,0 +1,40 @@ +package com.evotech.hd.cloud.utils.components; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.evotech.hd.cloud.rpc.ResourceService; +import com.evotech.hd.common.core.entity.Result; +import com.evotech.hd.common.core.entity.resource.dict.Dict; +import com.evotech.hd.common.core.enums.CodeMsg; +import com.evotech.hd.common.redis.utils.RedisUtil; + +import cn.hutool.json.JSONUtil; +import jakarta.annotation.Resource; + +@Component +public class HDStepDictComponent { + + private static String stepPrefix = "hd:resource:dict:hdstep-"; + + @Resource + private RedisUtil redisUtil; + @Resource + private ResourceService resourceService; + + public String hdStepDictName(Integer step) { + if (!redisUtil.hasKey(stepPrefix + step)) { + Result> res = resourceService.listDict("hdstate"); + if (CodeMsg.SUCCESS.getCode().equals(res.getCode())) { + List list = JSONUtil.toList(JSONUtil.parseArray(res.getData()), Dict.class); + list.stream().forEach(i -> redisUtil.set(stepPrefix + i.getDictValue(), i.getDictName())); + } else { + return null; + } + } + + return redisUtil.get(stepPrefix + step).toString(); + } + +} diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/SwapOrderBasicFeeComponent.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/SwapOrderBasicFeeComponent.java new file mode 100644 index 0000000..2fbf04a --- /dev/null +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/utils/components/SwapOrderBasicFeeComponent.java @@ -0,0 +1,49 @@ +package com.evotech.hd.cloud.utils.components; + +import java.time.LocalTime; +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.evotech.hd.cloud.dao.BatteryStationHdFeeStandardDao; +import com.evotech.hd.common.core.entity.cloud.BatteryStationHdFeeStandard; +import com.evotech.hd.common.core.entity.cloud.BatteryStationHdFeeStandardDetail; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import jakarta.annotation.Resource; + +@Component +public class SwapOrderBasicFeeComponent { + + @Resource + private BatteryStationHdFeeStandardDao batteryStationHdFeeStandardDao; + + + public OrderSwapBattery orderBasicFee(OrderSwapBattery osb) { + List list = batteryStationHdFeeStandardDao.listFeeStandard(osb.getStationCode(), DateUtil.format(osb.getOrderTime(), DatePattern.PURE_DATE_FORMATTER)); + if (!list.isEmpty()) { + BatteryStationHdFeeStandard standard = list.get(0); + List detailList = standard.getDetailList(); + if (!detailList.isEmpty()) { + detailList = detailList.stream().filter(i -> i.getTimeBegin().compareTo(LocalTime.now()) <= 0) + .filter(i -> i.getTimeEnd().compareTo(LocalTime.now()) >= 0).toList(); + if (!detailList.isEmpty()) { + BatteryStationHdFeeStandardDetail detail = detailList.get(0); + osb.setBasicFee(detail.getEachKwhFee()); + osb.setServiceFee(detail.getTimeServiceFee()); + } else { + osb.setBasicFee(standard.getEachKwhFee()); + osb.setServiceFee(standard.getCommonRemainFee()); + } + } else { + osb.setBasicFee(standard.getEachKwhFee()); + osb.setServiceFee(standard.getCommonRemainFee()); + } + } + + return osb; + } + +} diff --git a/cloud-manage-server/src/main/resources/application.yml b/cloud-manage-server/src/main/resources/application.yml index 4e1ff89..40c9406 100644 --- a/cloud-manage-server/src/main/resources/application.yml +++ b/cloud-manage-server/src/main/resources/application.yml @@ -13,6 +13,11 @@ spring: # 服务名称必须带上,不然nacos服务列表中没有,也不会有注册成功的信息 application: name: cloud-server + jackson: + timeZone: GMT+08:00 + date-format: yyyy-MM-dd HH:mm:ss + serialization: + write-dates-as-timestamps: false config: import: - nacos:${spring.application.name}.yaml?refreshEnabled=true diff --git a/cloud-manage-server/src/test/java/com/evotech/hd/cloud/CloudManageServerApplicationTests.java b/cloud-manage-server/src/test/java/com/evotech/hd/cloud/CloudManageServerApplicationTests.java index 42943ae..0b7e008 100644 --- a/cloud-manage-server/src/test/java/com/evotech/hd/cloud/CloudManageServerApplicationTests.java +++ b/cloud-manage-server/src/test/java/com/evotech/hd/cloud/CloudManageServerApplicationTests.java @@ -3,11 +3,24 @@ package com.evotech.hd.cloud; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import com.evotech.hd.cloud.rpc.ResourceService; +import com.evotech.hd.cloud.utils.components.HDStepDictComponent; +import jakarta.annotation.Resource; + @SpringBootTest class CloudManageServerApplicationTests { + + @Resource + private HDStepDictComponent hdStepDictComponent; + @Resource + private ResourceService resourceService; @Test void contextLoads() { + for (int i = 1; i < 9; i++) { + System.out.println(hdStepDictComponent.hdStepDictName(i)); + } + } } diff --git a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/AuthorizationManager.java b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/AuthorizationManager.java index 723c047..92523a1 100644 --- a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/AuthorizationManager.java +++ b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/AuthorizationManager.java @@ -3,6 +3,7 @@ package com.evotech.hd.gateway.oauth2; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Value; @@ -55,17 +56,19 @@ public class AuthorizationManager implements ReactiveAuthorizationManager" + uri); // 1. 对应跨域的预检请求直接放行 if (request.getMethod() == HttpMethod.OPTIONS) { return Mono.just(new AuthorizationDecision(true)); } - // 微信服务将UID放入请求头,验证一下 + // 2. 微信服务token验证 if (uri.contains("/gateway/wechat/")) { + // 提到另一个类了,应该走不到这了 return wechatTokenCheck(request, uri); } - // 2. token验证 + // 3. 其他服务token验证 /** * 这个类主要是处理权限(Authorization)的,对于身份(authentication) * 验证是在 @org.springframework.security.oauth2.server.resource.authentication.JwtReactiveAuthenticationManager @@ -107,17 +110,27 @@ public class AuthorizationManager implements ReactiveAuthorizationManager m = wechatService.tokenBuilder(wuid); - throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_INVALID.getCode(), CodeMsg.WECHAT_TOKEN_INVALID.getMsg(), JSONUtil.toJsonStr(m))); + CompletableFuture> asyncRes = CompletableFuture.supplyAsync(() -> { + return wechatService.tokenBuilder(wuid); + }); + Map m = null; + try { + m = asyncRes.get(); + } catch (Exception e) { + e.printStackTrace(); + throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), "token异常")); + } + throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_EXPIRED.getCode(), CodeMsg.WECHAT_TOKEN_EXPIRED.getMsg(), JSONUtil.toJsonStr(m))); + } else { // 缓存还有 if (wxToken.equals(redisUtil.get(HDConstant.wxToken + wuid).toString())) { return Mono.just(new AuthorizationDecision(true)); } else { // token对不上 - throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), "token异常")); + throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_INVALID.getCode(), CodeMsg.WECHAT_TOKEN_INVALID.getMsg(), "token异常")); } } } diff --git a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/ResourceServerConfig.java b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/ResourceServerConfig.java index e90b4d5..8804189 100644 --- a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/ResourceServerConfig.java +++ b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/ResourceServerConfig.java @@ -30,6 +30,8 @@ public class ResourceServerConfig { @Resource private AuthorizationManager authorizationManager; @Resource + private WechatAuthorizationManager wxAuthorizationManager; + @Resource private RSAKeyPair rsaKeyPair; @@ -66,7 +68,7 @@ public class ResourceServerConfig { exchange .pathMatchers(Convert.toStrArray(ignoreUri.getIgnoreUris())).permitAll() .pathMatchers(ignoreFixedUris()).permitAll() - .pathMatchers("/gateway/wechat/*").access(authorizationManager) + .pathMatchers("/gateway/wechat/**").access(wxAuthorizationManager) // .anyExchange().authenticated() // 其他走自定义逻辑 .anyExchange().access(authorizationManager) diff --git a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/WechatAuthorizationManager.java b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/WechatAuthorizationManager.java index a1c22ef..cb04a45 100644 --- a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/WechatAuthorizationManager.java +++ b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/WechatAuthorizationManager.java @@ -1,6 +1,8 @@ package com.evotech.hd.gateway.oauth2; import java.util.Map; +import java.util.concurrent.CompletableFuture; + import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; @@ -40,12 +42,14 @@ public class WechatAuthorizationManager implements ReactiveAuthorizationManager< @Override public Mono check(Mono mono, AuthorizationContext authorizationContext) { + System.out.println("\r\n===>>>进微信权限检查的了........."); + if (isPass) { return Mono.just(new AuthorizationDecision(true)); } ServerHttpRequest request = authorizationContext.getExchange().getRequest(); String uri = request.getURI().toString(); - + System.out.println("*****>" + uri); // 1. 对应跨域的预检请求直接放行 if (request.getMethod() == HttpMethod.OPTIONS) { return Mono.just(new AuthorizationDecision(true)); @@ -76,17 +80,31 @@ public class WechatAuthorizationManager implements ReactiveAuthorizationManager< if (!redisUtil.hasKey(HDConstant.wxToken + wuid)) { // 缓存没了,过期了 if (!wxToken.equals(XCXUtil.wechatToken(wuid, redisUtil.get(HDConstant.tokenRandomStr + wuid).toString()))) { - throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), "token异常")); + System.out.println("------555------"); + throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_INVALID.getCode(), CodeMsg.WECHAT_TOKEN_INVALID.getMsg(), "token异常")); } - Map m = wechatService.tokenBuilder(wuid); - throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_INVALID.getCode(), CodeMsg.WECHAT_TOKEN_INVALID.getMsg(), JSONUtil.toJsonStr(m))); + System.out.println("------666------"); + CompletableFuture> asyncRes = CompletableFuture.supplyAsync(() -> { + return wechatService.tokenBuilder(wuid); + }); + Map m = null; + try { + m = asyncRes.get(); + System.out.println("---777---" + m); + } catch (Exception e) { + e.printStackTrace(); + throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), "token异常")); + } + throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_EXPIRED.getCode(), CodeMsg.WECHAT_TOKEN_EXPIRED.getMsg(), JSONUtil.toJsonStr(m))); + } else { // 缓存还有 if (wxToken.equals(redisUtil.get(HDConstant.wxToken + wuid).toString())) { return Mono.just(new AuthorizationDecision(true)); } else { // token对不上 - throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), "token异常")); + System.out.println("-----88888----"); + throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_INVALID.getCode(), CodeMsg.WECHAT_TOKEN_INVALID.getMsg(), "token异常")); } } } diff --git a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionHandler.java b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionHandler.java index 2ec6be1..f4bc286 100644 --- a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionHandler.java +++ b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionHandler.java @@ -51,7 +51,6 @@ public class GlobalExceptionHandler extends DefaultErrorWebExceptionHandler { protected Mono renderErrorResponse(ServerRequest request) { // Map error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); Throwable throwable = getError(request); - System.out.println("1111666"); return ServerResponse // .status(super.getHttpStatus(error)) .status(HttpStatus.OK) diff --git a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionType.java b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionType.java index baf1b87..b16f98f 100644 --- a/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionType.java +++ b/gateway-server/src/main/java/com/evotech/hd/gateway/oauth2/exception/GlobalExceptionType.java @@ -7,6 +7,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import com.evotech.hd.common.core.entity.Result; +import cn.hutool.json.JSONUtil; + /** * 统一异常 @@ -31,7 +33,7 @@ public class GlobalExceptionType { public Result oAuth2AuthorizationHandle(OAuth2AuthorizationException e) { e.printStackTrace(); OAuth2Error error = e.getError(); - return new Result().bussinessException(error.getErrorCode(), error.getDescription(), error.getUri()); + return new Result().bussinessException(error.getErrorCode(), error.getDescription(), JSONUtil.isTypeJSON(error.getUri())?JSONUtil.parseObj(error.getUri()):error.getUri()); } diff --git a/resource-server/src/main/java/com/evotech/hd/resource/service/impl/DictServiceImpl.java b/resource-server/src/main/java/com/evotech/hd/resource/service/impl/DictServiceImpl.java index 71691ff..badc42a 100644 --- a/resource-server/src/main/java/com/evotech/hd/resource/service/impl/DictServiceImpl.java +++ b/resource-server/src/main/java/com/evotech/hd/resource/service/impl/DictServiceImpl.java @@ -78,6 +78,7 @@ public class DictServiceImpl implements DictService { @Override public Result addDict(Dict d) { + d.setCtime(new Date()); int n = dictDao.insert(d); return new Result().success(n); } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java b/wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java new file mode 100644 index 0000000..906e3db --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java @@ -0,0 +1,32 @@ +package com.evotech.hd.wechat.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Configuration +@ConfigurationProperties(prefix = "hbyt.gzh", ignoreUnknownFields = true) +@Data +@Schema(description = "公众号信息") +public class GZHProperties { + + private String appid; + + private String appSecret; + + private String token; + + private String encodingAESKey; + + private String preOrderTemplateId; + + private String orderStartTemplateId; + + private String orderSwapEndTemplateId; + + private String orderToPayTemplateId; + + private String orderEndTemplateId; +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/CloudServeController.java b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/CloudServeController.java index 9aafcb8..81b754e 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/CloudServeController.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/CloudServeController.java @@ -16,6 +16,7 @@ import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryStep; import com.evotech.hd.common.core.entity.cloud.PageListSwapOrderRequest; +import com.evotech.hd.common.core.entity.cloud.VehicleInfo; import com.evotech.hd.common.core.entity.cloud.vo.BatteryStationVO; import com.evotech.hd.wechat.service.CloudService; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; @@ -89,5 +90,13 @@ public class CloudServeController { public Result> companyByCode(String ccode) { return cloudService.companyByCode(ccode); } + + + @Operation(summary = "查询微信用户车辆") + @GetMapping("/wechatuser/carlist") + @ApiOperationSupport(order = 11) + public Result> listWechatUserCar(@NotBlank @RequestParam String wuid) { + return cloudService.listWechatUserCar(wuid); + } } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/XCXQRCodeController.java b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/XCXQRCodeController.java index 43c3191..19b470f 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/XCXQRCodeController.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/XCXQRCodeController.java @@ -7,6 +7,8 @@ import org.springframework.web.bind.annotation.RestController; import com.evotech.hd.wechat.service.XCXQRCodeService; import com.github.xiaoymin.knife4j.annotations.ApiSupport; + +import io.swagger.v3.oas.annotations.Hidden; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; @@ -14,6 +16,7 @@ import jakarta.servlet.http.HttpServletResponse; @RestController @RequestMapping("/xcx/qrcode") @ApiSupport(order = 16) +@Hidden public class XCXQRCodeController { diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageReceiveController.java b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageReceiveController.java new file mode 100644 index 0000000..e2492e2 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageReceiveController.java @@ -0,0 +1,36 @@ +package com.evotech.hd.wechat.controller.gzh; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import com.evotech.hd.wechat.entity.gzh.GZHWechatSigDTO; +import com.evotech.hd.wechat.service.gzh.GZHMessageReceiveService; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; + +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; + +@Tag(name = "公众号接收消息") +@RestController +@RequestMapping("/gzh/msg/receive") +@ApiSupport(order = 30) +@Hidden +public class GZHMessageReceiveController { + + @Resource + private GZHMessageReceiveService messageReceiveService; + + + @Operation(summary = "接收微信公众号推送的消息") + @RequestMapping(value = "/handle", method = {RequestMethod.GET, RequestMethod.POST}) + @ApiOperationSupport(order = 1) + public String messageHandle(GZHWechatSigDTO sigDto, HttpServletRequest request) { + return messageReceiveService.messageHandle(sigDto, request); + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java new file mode 100644 index 0000000..ea3b044 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java @@ -0,0 +1,56 @@ +package com.evotech.hd.wechat.controller.gzh; + +import org.springdoc.core.annotations.ParameterObject; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.evotech.hd.common.core.entity.Result; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; +import com.evotech.hd.wechat.service.gzh.GZHMessageTemplateService; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; + +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; + +@Tag(name = "公众号发送消息") +@RestController +@RequestMapping("/gzh/msg/send") +@ApiSupport(order = 31) +public class GZHMessageSendController { + + @Resource + private GZHMessageTemplateService gzhMessageTemplateService; + + + @Operation(summary = "预约发送公众号消息") + @PostMapping("/preorder") + @ApiOperationSupport(order = 1) + public Result preOrderMessage(@ParameterObject OrderSwapBatteryPre osbp) { + return gzhMessageTemplateService.sendTemplateMessageOrderPre(osbp); + } + + + @Operation(summary = "推送公众号订单消息") + @PostMapping("/order") + @ApiOperationSupport(order = 2) + public Result orderMessage(@ParameterObject OrderSwapBattery osb, @RequestParam Integer templateType) { + return gzhMessageTemplateService.sendTemplateMessageOrder(osb, templateType); + } + + + @Operation(summary = "预约发送公众号消息2") + @PostMapping("/preorder2") + @ApiOperationSupport(order = 3) + @Hidden + public Result preOrderMessage2(@RequestBody OrderSwapBatteryPre osbp) { + return gzhMessageTemplateService.sendTemplateMessageOrderPre(osbp); + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHSubscribeEvent.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHSubscribeEvent.java new file mode 100644 index 0000000..0f940e7 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHSubscribeEvent.java @@ -0,0 +1,27 @@ +package com.evotech.hd.wechat.entity.gzh; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(name = "公众号关注事件消息实体") +public class GZHSubscribeEvent { + + @Schema(description = "开发者微信号") + private String ToUserName; + + @Schema(description = "发送方账号(一个OpenID)") + private String FromUserName; + + @Schema(description = "消息创建时间 (整型)") + private Integer CreateTime; + + @Schema(description = "消息类型,event") + private String MsgType; + + @Schema(description = "事件类型,subscribe(订阅)、unsubscribe(取消订阅)") + private String Event; + + private String EventKey; + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHWechatSigDTO.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHWechatSigDTO.java new file mode 100644 index 0000000..3fbcf1a --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/GZHWechatSigDTO.java @@ -0,0 +1,23 @@ +package com.evotech.hd.wechat.entity.gzh; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(name = "公众号签名验证时发送的参数") +public class GZHWechatSigDTO { + + @Schema(description = "微信加密签名") + private String signature; + + @Schema(description = "时间戳") + private String timestamp; + + @Schema(description = "随机数") + private String nonce; + + @Schema(description = "随机字符串") + private String echostr; + + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/ChargeTemplateData.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/ChargeTemplateData.java new file mode 100644 index 0000000..a4a0d03 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/ChargeTemplateData.java @@ -0,0 +1,53 @@ +package com.evotech.hd.wechat.entity.gzh.templatemessage; + +import cn.hutool.json.JSONObject; +import lombok.Getter; + +/** + * 充电完成 模板消息 关键词 + */ +@Getter +public class ChargeTemplateData { + + private JSONObject character_string14; + + private JSONObject character_string31; + + private JSONObject character_string25; + + private JSONObject amount34; + + private JSONObject amount28; + + + public void setCharacter_string14(String value1) { + JSONObject jo = new JSONObject(); + jo.set("value", value1); + this.character_string14 = jo; + } + + public void setCharacter_string31(String value2) { + JSONObject jo = new JSONObject(); + jo.set("value", value2); + this.character_string31 = jo; + } + + public void setCharacter_string25(String value3) { + JSONObject jo = new JSONObject(); + jo.set("value", value3); + this.character_string25 = jo; + } + + public void setAmount34(String value4) { + JSONObject jo = new JSONObject(); + jo.set("value", value4); + this.amount34 = jo; + } + + public void setAmount28(String value5) { + JSONObject jo = new JSONObject(); + jo.set("value", value5); + this.amount28 = jo; + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/MessageTemplateSendData.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/MessageTemplateSendData.java new file mode 100644 index 0000000..bd65add --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/MessageTemplateSendData.java @@ -0,0 +1,35 @@ +package com.evotech.hd.wechat.entity.gzh.templatemessage; + +import java.io.Serializable; + +import cn.hutool.json.JSONObject; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; +import lombok.Data; + +@Data +public class MessageTemplateSendData implements Serializable { + + private static final long serialVersionUID = -8911097073333862L; + + @Schema(description = "接收者openid", requiredMode = RequiredMode.REQUIRED) + private String touser; + + @Schema(description = "模板ID", requiredMode = RequiredMode.REQUIRED) + private String template_id; + + @Schema(description = "模板跳转链接") + private String url; + + @Schema(description = "跳小程序所需数据,不需跳小程序可不用传该数据") + private Miniprogram miniprogram; + + @Schema(description = "防重入id。对于同一个openid + client_msg_id, 只发送一条消息,10分钟有效") + private String client_msg_id; + + @Schema(description = "模板数据") + private JSONObject data; + +} + + diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/Miniprogram.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/Miniprogram.java new file mode 100644 index 0000000..3e98541 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/Miniprogram.java @@ -0,0 +1,15 @@ +package com.evotech.hd.wechat.entity.gzh.templatemessage; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class Miniprogram { + + @Schema(description = "所需跳转到的小程序appid") + private String appid; + + @Schema(description = "所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar)") + private String path; + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PayTemplateData.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PayTemplateData.java new file mode 100644 index 0000000..ce1d2ea --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PayTemplateData.java @@ -0,0 +1,53 @@ +package com.evotech.hd.wechat.entity.gzh.templatemessage; + +import cn.hutool.json.JSONObject; +import lombok.Getter; + +/** + * 支付完成 模板消息 关键词 + */ +@Getter +public class PayTemplateData { + + private JSONObject character_string1; + + private JSONObject car_number10; + + private JSONObject thing2; + + private JSONObject amount6; + + private JSONObject time9; + + + public void setCharacter_string1(String value1) { + JSONObject jo = new JSONObject(); + jo.set("value", value1); + this.character_string1 = jo; + } + + public void setCar_number10(String value2) { + JSONObject jo = new JSONObject(); + jo.set("value", value2); + this.car_number10 = jo; + } + + public void setThing2(String value3) { + JSONObject jo = new JSONObject(); + jo.set("value", value3); + this.thing2 = jo; + } + + public void setAmount6(String value4) { + JSONObject jo = new JSONObject(); + jo.set("value", value4); + this.amount6 = jo; + } + + public void setTime9(String value5) { + JSONObject jo = new JSONObject(); + jo.set("value", value5); + this.time9 = jo; + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PreOrderTemplateData.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PreOrderTemplateData.java new file mode 100644 index 0000000..d44f4d4 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/PreOrderTemplateData.java @@ -0,0 +1,49 @@ +package com.evotech.hd.wechat.entity.gzh.templatemessage; + +import cn.hutool.json.JSONObject; +import lombok.Getter; + +@Getter +public class PreOrderTemplateData { + + private JSONObject car_number1; + + private JSONObject thing2; + + private JSONObject time3; + + private JSONObject thing5; + + private JSONObject phone_number4; + + public void setCar_number1(String value1) { + JSONObject jo = new JSONObject(); + jo.set("value", value1); + this.car_number1 = jo; + } + + public void setThing2(String value2) { + JSONObject jo = new JSONObject(); + jo.set("value", value2); + this.thing2 = jo; + } + + public void setTime3(String value3) { + JSONObject jo = new JSONObject(); + jo.set("value", value3); + this.time3 = jo; + } + + public void setThing5(String value4) { + JSONObject jo = new JSONObject(); + jo.set("value", value4); + this.thing5 = jo; + } + + public void setPhone_number4(String value4) { + JSONObject jo = new JSONObject(); + jo.set("value", value4); + this.phone_number4 = jo; + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/SwapTemplateData.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/SwapTemplateData.java new file mode 100644 index 0000000..5758fc2 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/SwapTemplateData.java @@ -0,0 +1,45 @@ +package com.evotech.hd.wechat.entity.gzh.templatemessage; + +import cn.hutool.json.JSONObject; +import lombok.Getter; + +/** + * 换电成功 模板消息 关键词 + */ +@Getter +public class SwapTemplateData { + + private JSONObject thing2; + + private JSONObject character_string3; + + private JSONObject character_string4; + + private JSONObject time5; + + + public void setThing2(String value1) { + JSONObject jo = new JSONObject(); + jo.set("value", value1); + this.thing2 = jo; + } + + public void setCharacter_string3(String value2) { + JSONObject jo = new JSONObject(); + jo.set("value", value2); + this.character_string3 = jo; + } + + public void setCharacter_string4(String value3) { + JSONObject jo = new JSONObject(); + jo.set("value", value3); + this.character_string4 = jo; + } + + public void setTime5(String value4) { + JSONObject jo = new JSONObject(); + jo.set("value", value4); + this.time5 = jo; + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/AccessTokenService.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/AccessTokenService.java index a707fb7..aa60a34 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/service/AccessTokenService.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/AccessTokenService.java @@ -19,7 +19,7 @@ public class AccessTokenService { @Resource private RedisUtil redisUtil; - private String accessTokenPrefix = "hd:wechat:accessToken:"; + private String accessTokenPrefix = "hd:wechat:accessToken:xcx:"; public String getAccessToken() { if (redisUtil.hasKey(accessTokenPrefix + xcxProperties.getAppid())) { @@ -31,7 +31,7 @@ public class AccessTokenService { if (StringUtils.hasText(jo.getStr("errcode"))) { throw new RuntimeException(res); } - redisUtil.set(accessTokenPrefix + xcxProperties.getAppid(), jo.getStr("access_token"), 7200L - 15); + redisUtil.set(accessTokenPrefix + xcxProperties.getAppid(), jo.getStr("access_token"), 7200L); return jo.getStr("access_token"); } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/CloudService.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/CloudService.java index dad1aed..9175e0f 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/service/CloudService.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/CloudService.java @@ -15,6 +15,7 @@ import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryStep; import com.evotech.hd.common.core.entity.cloud.PageListSwapOrderRequest; +import com.evotech.hd.common.core.entity.cloud.VehicleInfo; import com.evotech.hd.common.core.entity.cloud.vo.BatteryStationVO; @FeignClient(value = "cloud-server") @@ -48,5 +49,9 @@ public interface CloudService { @GetMapping(value = "/cloud/company/companyByCode", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public Result> companyByCode(@RequestParam String ccode); + + @GetMapping(value = "/cloud/vehicle/wechatuser/relation/list", + consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) + public Result> listWechatUserCar(@RequestParam String wuid); } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHAccessTokenService.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHAccessTokenService.java new file mode 100644 index 0000000..5bdee0f --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHAccessTokenService.java @@ -0,0 +1,38 @@ +package com.evotech.hd.wechat.service.gzh; + +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import com.evotech.hd.common.redis.utils.RedisUtil; +import com.evotech.hd.wechat.config.GZHProperties; +import com.evotech.hd.wechat.utils.xcx.AccessTokenUtil; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import jakarta.annotation.Resource; + +@Service +public class GZHAccessTokenService { + + @Resource + private GZHProperties gzhProperties; + @Resource + private RedisUtil redisUtil; + + private String accessTokenPrefix = "hd:wechat:accessToken:gzh:"; + + public String gzhAccessToken() { + if (redisUtil.hasKey(accessTokenPrefix + gzhProperties.getAppid())) { + return redisUtil.get(accessTokenPrefix + gzhProperties.getAppid()).toString(); + } + String res = AccessTokenUtil.accessToken(gzhProperties.getAppid(), gzhProperties.getAppSecret()); + JSONObject jo = JSONUtil.parseObj(res); + // {"errcode":40013,"errmsg":"invalid appid rid: 6708ba65-0b425b74-4620599c"} + if (StringUtils.hasText(jo.getStr("errcode"))) { + throw new RuntimeException(res); + } + redisUtil.set(accessTokenPrefix + gzhProperties.getAppid(), jo.getStr("access_token"), 7200L); + return jo.getStr("access_token"); + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageReceiveService.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageReceiveService.java new file mode 100644 index 0000000..010d49e --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageReceiveService.java @@ -0,0 +1,106 @@ +package com.evotech.hd.wechat.service.gzh; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.evotech.hd.common.core.dao.wechat.WechatUserDao; +import com.evotech.hd.common.core.entity.wechat.WechatUser; +import com.evotech.hd.wechat.config.GZHProperties; +import com.evotech.hd.wechat.entity.gzh.GZHWechatSigDTO; +import com.evotech.hd.wechat.utils.gzh.OpenId2UnionIdUtil; + +import cn.hutool.core.util.XmlUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; + +@Service +public class GZHMessageReceiveService { + + @Resource + private GZHProperties gzhProperties; + @Resource + private GZHAccessTokenService gzhAccessTokenService; + @Resource + private WechatUserDao wechatUserDao; + + + public String messageHandle(GZHWechatSigDTO sigDto, HttpServletRequest request) { + if (!isFromWechat(sigDto.getSignature(), sigDto.getTimestamp(), sigDto.getNonce())) { + System.out.println("XXXXXXXXXXXXXXXXXX"); + return ""; + } + try { + System.out.println("++++++++"); + String res = HttpUtil.getString(request.getInputStream(), Charset.defaultCharset(), false); + Map map = XmlUtil.xmlToMap(res); + if ("event".equals(map.get("MsgType").toString())) { + switch (map.get("Event").toString()) { + case "subscribe": + subscribeEventHandle(map); + break; + case "unsubscribe": + + break; + default: + break; + } + } + + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return ""; + + } + + + /** + * 订阅事件处理 + * @param map + */ + private void subscribeEventHandle(Map map) { + String openid = map.get("FromUserName").toString(); + String gzhid = map.get("ToUserName").toString(); + String res = OpenId2UnionIdUtil.gzhUserInfo(gzhAccessTokenService.gzhAccessToken(), openid); + JSONObject jo = JSONUtil.parseObj(res); + if (!jo.containsKey("errcode")) { + String unionid = jo.getStr("unionid"); + WechatUser user = new WechatUser(); + user.setGzhId(gzhid); + user.setGzhOpenid(openid); + wechatUserDao.update(user, new QueryWrapper().eq("unionid", unionid)); + } + } + + + + /** + * 验证微信签名 + * @param signature + * @param timestamp + * @param nonce + * @return + */ + private Boolean isFromWechat(String signature, String timestamp, String nonce) { + List list = new ArrayList<>(); + list.add(gzhProperties.getToken()); + list.add(timestamp); + list.add(nonce); + Collections.sort(list); + return signature.equals(SecureUtil.sha1(list.get(0) + list.get(1) + list.get(2))); + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java new file mode 100644 index 0000000..4aa0b17 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java @@ -0,0 +1,164 @@ +package com.evotech.hd.wechat.service.gzh; + +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.evotech.hd.common.core.dao.wechat.WechatUserDao; +import com.evotech.hd.common.core.entity.Result; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; +import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre; +import com.evotech.hd.common.core.entity.wechat.WechatUser; +import com.evotech.hd.common.core.enums.CodeMsg; +import com.evotech.hd.wechat.config.GZHProperties; +import com.evotech.hd.wechat.config.XcxProperties; +import com.evotech.hd.wechat.entity.gzh.templatemessage.ChargeTemplateData; +import com.evotech.hd.wechat.entity.gzh.templatemessage.MessageTemplateSendData; +import com.evotech.hd.wechat.entity.gzh.templatemessage.Miniprogram; +import com.evotech.hd.wechat.entity.gzh.templatemessage.PayTemplateData; +import com.evotech.hd.wechat.entity.gzh.templatemessage.PreOrderTemplateData; +import com.evotech.hd.wechat.entity.gzh.templatemessage.SwapTemplateData; +import com.evotech.hd.wechat.utils.gzh.TemplateMessageUtil; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import jakarta.annotation.Resource; + +@Service +public class GZHMessageTemplateService { + + + private static String preOrderPage = "pages/home/index"; + + private static String orderPage = "pages/home/index"; + + private static String orderDetailPage = "pages/home/index"; + + + @Resource + private GZHAccessTokenService gzhAccessTokenService; + @Resource + private GZHProperties gzhProperties; + @Resource + private XcxProperties xcxProperties; + @Resource + private WechatUserDao wechatUserDao; + + + + /** + * 预约完成推送公众号消息 + * @param osbp + * @return + */ + public Result sendTemplateMessageOrderPre(OrderSwapBatteryPre osbp) { + WechatUser wuser = wechatUserDao.selectOne(new QueryWrapper().eq("wuid", osbp.getUcode())); + if (wuser == null) { + return null; + } + if (!StringUtils.hasText(wuser.getGzhOpenid())) { + return new Result().error("未关注公众号!"); + } + MessageTemplateSendData sendData = new MessageTemplateSendData(); + sendData.setTouser(wuser.getGzhOpenid()); + + sendData.setTemplate_id(gzhProperties.getPreOrderTemplateId()); + + Miniprogram miniprogram = new Miniprogram(); + miniprogram.setAppid(xcxProperties.getAppid()); + miniprogram.setPath(preOrderPage); + sendData.setMiniprogram(miniprogram); + + PreOrderTemplateData data = new PreOrderTemplateData(); + data.setCar_number1(osbp.getPlateNum()); + data.setThing2(osbp.getStationName()); + data.setTime3(DateUtil.format(osbp.getReservationTime(), DatePattern.NORM_DATETIME_FORMATTER)); + data.setThing5(osbp.getUname()); + data.setPhone_number4(osbp.getPhone()); + sendData.setData(JSONUtil.parseObj(data)); + + String res = TemplateMessageUtil.templateMessageSend(gzhAccessTokenService.gzhAccessToken(), sendData); + JSONObject jo = JSONUtil.parseObj(res); + if (jo.getInt("errcode") == 0) { + return new Result().success(jo); + } + return new Result().error(CodeMsg.WECHAT_API_ERROR, jo); + } + + /** + * 推送公众号订单消息 + * @param osb + * @param templateType + * @return + */ + public Result sendTemplateMessageOrder(OrderSwapBattery osb, Integer templateType) { + if (!StringUtils.hasText(osb.getOrderPreUid())) { + return null; + } + WechatUser wuser = wechatUserDao.selectOne(new QueryWrapper().eq("wuid", osb.getOrderPreUid())); + if (wuser == null) { + return null; + } + if (!StringUtils.hasText(wuser.getGzhOpenid())) { + return new Result().error("未关注公众号!"); + } + + MessageTemplateSendData sendData = new MessageTemplateSendData(); + sendData.setTouser(wuser.getGzhOpenid()); + String templateId = ""; + Miniprogram miniprogram = new Miniprogram(); + miniprogram.setAppid(xcxProperties.getAppid()); + switch (templateType) { + // 换电完成 + case 1: + templateId = gzhProperties.getOrderSwapEndTemplateId(); + miniprogram.setPath(orderPage); + SwapTemplateData data = new SwapTemplateData(); + data.setThing2(osb.getStationName()); + data.setCharacter_string3(osb.getReturnBatCode()); + data.setCharacter_string4(osb.getRentBatCode()); + data.setTime5(DateUtil.format(osb.getOrderTime(), DatePattern.NORM_DATETIME_FORMATTER)); + sendData.setData(JSONUtil.parseObj(data)); + break; + // 充电完成,待结算 + case 2: + templateId = gzhProperties.getOrderEndTemplateId(); + miniprogram.setPath(orderPage); + ChargeTemplateData chargeData = new ChargeTemplateData(); + chargeData.setCharacter_string14(osb.getOrderNo()); + chargeData.setCharacter_string31(osb.getReturnBatCode()); + chargeData.setCharacter_string25(osb.getElectAmount() + ""); + chargeData.setAmount34(osb.getServiceFee().toString()); + chargeData.setAmount28(osb.getAmount() + ""); + sendData.setData(JSONUtil.parseObj(chargeData)); + break; + // 付款完成 + case 3: + templateId = gzhProperties.getOrderSwapEndTemplateId(); + miniprogram.setPath(orderDetailPage); + PayTemplateData payData = new PayTemplateData(); + payData.setThing2(osb.getStationName()); + payData.setCharacter_string1(osb.getOrderNo()); + payData.setCar_number10(osb.getPlateNum()); + payData.setAmount6(osb.getAmount() + ""); + payData.setTime9(""); + sendData.setData(JSONUtil.parseObj(payData)); + break; + default: + break; + } + + sendData.setTemplate_id(templateId); + sendData.setMiniprogram(miniprogram); + + String res = TemplateMessageUtil.templateMessageSend(gzhAccessTokenService.gzhAccessToken(), sendData); + JSONObject jo = JSONUtil.parseObj(res); + if (jo.getInt("errcode") == 0) { + return new Result().success(jo); + } + return new Result().error(CodeMsg.WECHAT_API_ERROR, jo); + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/OpenId2UnionIdUtil.java b/wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/OpenId2UnionIdUtil.java new file mode 100644 index 0000000..aa2391c --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/OpenId2UnionIdUtil.java @@ -0,0 +1,27 @@ +package com.evotech.hd.wechat.utils.gzh; + +import java.util.HashMap; +import java.util.Map; + +import cn.hutool.http.HttpUtil; + +public class OpenId2UnionIdUtil { + +private static String gzhUserInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="; + + + /** + *获取用户基本信息(UnionID机制) GET + * @param accessToken + * @param openid + * @return + */ + public static String gzhUserInfo(String accessToken, String openid) { + Map m = new HashMap(); + m.put("openid", openid); + m.put("lang", "zh_CN"); + String res = HttpUtil.get(gzhUserInfoUrl + accessToken, m); + return res; + } + +} diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/TemplateMessageUtil.java b/wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/TemplateMessageUtil.java new file mode 100644 index 0000000..6aa6133 --- /dev/null +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/utils/gzh/TemplateMessageUtil.java @@ -0,0 +1,30 @@ +package com.evotech.hd.wechat.utils.gzh; + +import com.evotech.hd.wechat.entity.gzh.templatemessage.MessageTemplateSendData; + +import cn.hutool.http.HttpRequest; +import cn.hutool.json.JSONUtil; + +public class TemplateMessageUtil { + + + private static String templateSendUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="; + + + /** + * 发送模板消息 POST + * @param accessToken + * @param templateData + * @return + */ + public static String templateMessageSend(String accessToken, MessageTemplateSendData templateData) { + String body = JSONUtil.toJsonStr(templateData); + String res = HttpRequest.post(templateSendUrl + accessToken) + .header("Content-Type", "application/json") + .body(body) + .execute() + .body(); + return res; + } + +} diff --git a/wechat-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/wechat-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json index fad132b..f42bde8 100644 --- a/wechat-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/wechat-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -43,5 +43,45 @@ "name": "hbyt.xcx.token_exp_hour", "type": "java.lang.String", "description": "A description for 'hbyt.xcx.token_exp_hour'" + }, + { + "name": "hbyt.gzh.appid", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.appid'" + }, + { + "name": "hbyt.gzh.app-secret", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.app-secret'" + }, + { + "name": "hbyt.gzh.pre_order_template_id", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.pre_order_template_id'" + }, + { + "name": "hbyt.gzh.order_start_template_id", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.order_start_template_id'" + }, + { + "name": "hbyt.gzh.order_swap_end_template_id", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.order_swap_end_template_id'" + }, + { + "name": "hbyt.gzh.order_to_pay_template_id", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.order_to_pay_template_id'" + }, + { + "name": "hbyt.gzh.order_end_template_id", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.order_end_template_id'" + }, + { + "name": "hbyt.gzh.encodingAESKey", + "type": "java.lang.String", + "description": "A description for 'hbyt.gzh.encodingAESKey'" } ]} \ No newline at end of file diff --git a/wechat-server/src/main/resources/application.yml b/wechat-server/src/main/resources/application.yml index d52859c..557fef6 100644 --- a/wechat-server/src/main/resources/application.yml +++ b/wechat-server/src/main/resources/application.yml @@ -44,6 +44,7 @@ management: # 微信 hbyt: + # 小程序 xcx: appid: wx2ab384cf1e6f85a1 app-secret: 6c55a398703529358eac398e2bc89ae2 @@ -58,4 +59,15 @@ hbyt: refund_notify_url: https://api.evo-techina.com/wechat/wechatpay/refundsback/msg # token缓存时效:小时 token_exp_hour: 2 + # 公众号 + gzh: + appid: wx268e32962db19f5f + app-secret: 84a6065165ec82862c5e03a010a6dc6c + token: r7YASMj3S9vCeeyJPpKeFPR9drhFaSDt + encodingAESKey: W3zDuKYFMUlYUXpT4AhRSPkqMS7CgcmnEVQ3enVcTtf + pre_order_template_id: 4eknqqZhEqW7_3xSYLskvPUX193irbalhdHjOSY88-g + order_start_template_id: L_AsG7s7DOyyz4dXLb8gIi7h4Sy__ifEAL1Mo8gAw4E + order_swap_end_template_id: wGll5W3NSHXkHjcEprjUbd1shigGOqywGX7A0BVnzUs + order_to_pay_template_id: IE0_RGuN5ufU4GFrCgM9JeUfvlWfbneEuUMDsn0RBQs + order_end_template_id: C5-AGh67aFXChQONqSwxaRrJgFrn_Z25VTlTk0jHSUY \ No newline at end of file