Files
jsowell-charger-web/jsowell-pile/src/main/java/com/jsowell/wxpay/service/WxAppletRemoteService.java

394 lines
16 KiB
Java
Raw Normal View History

2023-03-04 16:29:55 +08:00
package com.jsowell.wxpay.service;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
2024-08-23 10:40:16 +08:00
import com.google.common.collect.Maps;
import com.jsowell.common.constant.CacheConstants;
2023-03-04 16:29:55 +08:00
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.StringUtils;
2025-12-15 10:06:15 +08:00
import com.jsowell.common.util.YKCUtils;
2023-03-04 16:29:55 +08:00
import com.jsowell.common.util.http.HttpUtils;
2023-08-23 15:36:14 +08:00
import com.jsowell.pile.domain.MemberBasicInfo;
2024-09-20 14:45:47 +08:00
import com.jsowell.pile.domain.OrderBasicInfo;
2024-01-06 15:20:28 +08:00
import com.jsowell.pile.service.MemberBasicInfoService;
2024-01-06 15:13:50 +08:00
import com.jsowell.pile.service.OrderBasicInfoService;
2024-08-23 10:37:08 +08:00
import com.jsowell.pile.service.PileBillingTemplateService;
2024-07-16 14:07:06 +08:00
import com.jsowell.pile.vo.uniapp.customer.CurrentTimePriceDetails;
import com.jsowell.pile.vo.uniapp.customer.SendMessageVO;
2025-12-15 10:06:15 +08:00
import com.jsowell.pile.vo.web.BillingTemplateVO;
2023-03-04 16:29:55 +08:00
import com.jsowell.wxpay.config.WeixinLoginProperties;
import com.jsowell.wxpay.dto.AppletTemplateMessageSendDTO;
import com.jsowell.wxpay.dto.WechatSendMsgDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
2023-03-04 16:29:55 +08:00
import java.util.HashMap;
import java.util.Map;
2024-02-28 15:22:38 +08:00
import java.util.Objects;
2023-03-04 16:29:55 +08:00
@Service
public class WxAppletRemoteService {
private Logger log = LoggerFactory.getLogger(WxAppletRemoteService.class);
private static final String WX_APPLET_URl = "https://api.weixin.qq.com/cgi-bin";
private static final String GET_USER_PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";
@Autowired
private ObjectMapper objectMapper;
@Autowired
private RedisCache redisCache;
@Autowired
2024-01-06 15:13:50 +08:00
private OrderBasicInfoService orderBasicInfoService;
2023-03-04 16:29:55 +08:00
@Autowired
2024-01-06 15:20:28 +08:00
private PileBillingTemplateService pileBillingTemplateService;
2023-08-23 15:36:14 +08:00
@Autowired
2024-01-06 15:20:28 +08:00
private MemberBasicInfoService memberBasicInfoService;
2023-08-23 15:36:14 +08:00
2023-03-04 16:29:55 +08:00
@Value("${weixin.login.appid}")
private String appid;
@Value("${weixin.login.appsecret}")
private String secret;
@Value("${weixin.sendMsg.startChargingTmpId}")
private String startChargingTmpId;
@Value("${weixin.sendMsg.stopChargingTmpId}")
private String stopChargingTmpId;
@Value("${weixin.sendMsg.startupResultTmpId}")
private String startupResultTmpId;
2023-03-04 16:29:55 +08:00
/**
* 获取accessToken
*
* @return
*/
public String getAccessToken() {
//查询token是否存在
String redisKey = CacheConstants.ACCESS_TOKEN + appid;
2023-03-04 16:29:55 +08:00
// 使用缓存先查询AccessToken是否存在
String accessToken = redisCache.getCacheObject(redisKey);
// 存在直接返回不存在重新获取AccessToken
if (!Strings.isNullOrEmpty(accessToken)) {
return accessToken;
}
// 获取AccessToken的url
String grantType = "client_credential";
// https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=
String url = WX_APPLET_URl + "/token?grant_type=" + grantType + "&appid=" + appid + "&secret=" + secret;
// 获取到AccessToken
String token = HttpUtils.sendGet(url);
Map<String, Object> map = null;
try {
map = objectMapper.readValue(token, Map.class);
} catch (IOException e) {
log.error("小程序异常通知-获取AccessToken-转化异常", e);
}
String access_token = String.valueOf(map.get("access_token"));
// 把AccessToken存入缓存中并设置过期时间因为access_token的过期时间是两小时我们缓存的时间一定要小于两小时
redisCache.setCacheObject(redisKey, access_token, 300);
if (map.get("errcode") != null || map.get("errmsg") != null) {
String errcode = String.valueOf(map.get("errcode"));
String errmsg = String.valueOf(map.get("errmsg"));
if (!errcode.equals("0")) {
log.error("获取token失败code=" + errcode + "msg=" + errmsg);
return null;
}
}
return access_token;
}
/**
* 获取手机号
*
* @param code
* @return
*/
public String getMobileNumberByCode(String code) {
if (StringUtils.isBlank(code)) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
// 请求获取令牌
String access_token = getAccessToken();
// 通过tokencode前端getPhoneNum按钮返回的code而不是登录的code发送post请求到官方获取到手机号码
String postUrl = GET_USER_PHONE_NUMBER_URL + "?access_token=" + access_token;
JSONObject paramJson = new JSONObject();
paramJson.put("code", code);
String postResult = HttpUtils.sendPost(postUrl, paramJson.toJSONString());
JSONObject postResultJson = JSONObject.parseObject(postResult);
String errCode = postResultJson.getString("errcode");
if (!StringUtils.equals(errCode, Constants.ZERO)) {
// errCode不为0表示有错误
String errMsg = postResultJson.getString("errmsg");
log.info("发送Post请求失败,错误消息:{}", errMsg);
throw new BusinessException(errCode, errMsg);
}
JSONObject phoneInfoJson = (JSONObject) postResultJson.get("phone_info");
return phoneInfoJson.getString("phoneNumber");
}
/**
* 获取openId
*
* @param code
* @return
*/
public String getOpenIdByCode(String code) {
String baseAccessTokenUrl = WeixinLoginProperties.WX_OPEN_GATEWAY +
"?appid=%s" +
"&secret=%s" +
"&js_code=%s" +
"&grant_type=authorization_code";
log.info("appid:{},appscrect:{}", WeixinLoginProperties.WX_OPEN_APP_ID, WeixinLoginProperties.WX_OPEN_APP_SECRET);
String accessTokenUrl = String.format(baseAccessTokenUrl, WeixinLoginProperties.WX_OPEN_APP_ID, WeixinLoginProperties.WX_OPEN_APP_SECRET, code);
//2执行请求获取微信请求返回得数据
String result = HttpUtils.sendGet(accessTokenUrl);
// 3 对微信返回得数据进行转换
Map<String, Object> resultMap = JSONObject.parseObject(result, HashMap.class);
log.info("微信返回的日志信息是code:{}resultMap{}", code, resultMap);
if (resultMap.get("errcode") != null) {
throw new BusinessException("22006", "微信登录出错!");
}
// 4: 解析微信用户得唯一凭证openid
String openid = (String) resultMap.get("openid");
if (StringUtils.isBlank(openid)) {
throw new BusinessException("22009", "登录失败,尝试刷新重新扫码登录!!!");
}
// 5封装返回
return openid;
}
/**
* 开始充电发送消息
2024-08-05 11:30:41 +08:00
* @param memberId 会员id
* @param orderCode 订单编号
2023-03-04 16:29:55 +08:00
* @return
*/
2024-08-05 11:30:41 +08:00
public Map<String, String> startChargingSendMsg(String memberId, String orderCode) {
MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(memberId);
if (memberBasicInfo == null) {
throw new BusinessException("99999", "开始充电发送消息 error, 查询openid为空");
}
2024-08-05 11:30:41 +08:00
WechatSendMsgDTO sendMsgDTO = new WechatSendMsgDTO();
sendMsgDTO.setOpenId(memberBasicInfo.getOpenId());
sendMsgDTO.setOrderCode(orderCode);
return this.startChargingSendMsg(sendMsgDTO);
2024-09-20 14:45:47 +08:00
}
public Map<String, String> startChargingSendMsg(OrderBasicInfo orderBasicInfo) {
MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(orderBasicInfo.getMemberId());
if (memberBasicInfo == null) {
throw new BusinessException("99999", "开始充电发送消息 error, 查询openid为空");
}
WechatSendMsgDTO sendMsgDTO = new WechatSendMsgDTO();
sendMsgDTO.setOpenId(memberBasicInfo.getOpenId());
sendMsgDTO.setOrderCode(orderBasicInfo.getOrderCode());
return this.startChargingSendMsg(sendMsgDTO);
2024-08-05 11:30:41 +08:00
}
/**
* 开始充电发送消息
* @param dto
* @return
*/
private Map<String, String> startChargingSendMsg(WechatSendMsgDTO dto) {
if (StringUtils.isBlank(dto.getOpenId()) || StringUtils.isBlank(dto.getOrderCode())) {
2023-03-04 16:29:55 +08:00
return null;
}
AppletTemplateMessageSendDTO msgInfo = new AppletTemplateMessageSendDTO();
2023-07-08 11:14:17 +08:00
msgInfo.setType(Constants.ONE); // 1-开始充电推送消息
2024-08-05 11:30:41 +08:00
msgInfo.setTouser(dto.getOpenId()); // 接收者的openId
2023-03-04 16:29:55 +08:00
// 通过orderCode查询到充电站点和开始时间并set
2024-08-05 11:30:41 +08:00
SendMessageVO sendMessageVO = orderBasicInfoService.selectOrderInfoByOrderCode(dto.getOrderCode());
2024-02-28 15:22:38 +08:00
if (Objects.isNull(sendMessageVO)) {
log.error("开始充电发送消息, 通过orderCode:{}, 查询SendMessageVO为null", dto.getOrderCode());
return null;
}
2023-03-04 16:29:55 +08:00
AppletTemplateMessageSendDTO.StartChargingMessage startChargingMessage = new AppletTemplateMessageSendDTO.StartChargingMessage();
msgInfo.setStartChargingMessage(startChargingMessage);
if (StringUtils.isBlank(sendMessageVO.getChargeStartTime())) {
startChargingMessage.setStartTime(DateUtils.dateTimeNow("yyyy-MM-dd HH:mm"));
}else {
startChargingMessage.setStartTime(sendMessageVO.getChargeStartTime()); // 开始时间
}
startChargingMessage.setStationName(sendMessageVO.getStationName()); // 站点名称
// 订单编号
2025-12-15 10:06:15 +08:00
String orderCode = sendMessageVO.getOrderCode();
startChargingMessage.setOrderCode(orderCode);
// 查询订单信息
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
if (orderBasicInfo == null) {
return null;
}
String pileSn = orderBasicInfo.getPileSn();
Boolean result = YKCUtils.checkEVPileSn(pileSn);
// 收费标准
CurrentTimePriceDetails currentTimePriceDetails = new CurrentTimePriceDetails();
if (result) {
// 查询电动汽车收费标准
currentTimePriceDetails = pileBillingTemplateService.getCurrentTimePriceDetails(sendMessageVO.getStationId());
}else {
// 查询电单车收费标准
currentTimePriceDetails = pileBillingTemplateService.getCurrentTimePriceDetailsForEBike(sendMessageVO.getStationId());
}
// 收费标准
2025-12-15 10:06:15 +08:00
// CurrentTimePriceDetails currentTimePriceDetails = pileBillingTemplateService.getCurrentTimePriceDetailsByPileType(sendMessageVO.getStationId(),sendMessageVO.getPileSn());
2025-12-13 16:53:23 +08:00
startChargingMessage.setTotalPrice(currentTimePriceDetails.getTotalPrice() + " 元/度");
// 枪口编号
startChargingMessage.setPileConnectorCode(sendMessageVO.getPileSn() + "" + sendMessageVO.getConnectorCode() + "枪口");
2024-08-05 15:46:59 +08:00
return uniAppSendMsg(msgInfo); // 开始充电
2023-03-04 16:29:55 +08:00
}
/**
* 停止充电发送消息
* @param dto
* @return
*/
public Map<String, String> stopChargingSendMsg(WechatSendMsgDTO dto) throws ParseException {
2023-03-04 16:29:55 +08:00
// 通过订单号查询订单金额
AppletTemplateMessageSendDTO msgInfo = new AppletTemplateMessageSendDTO();
SendMessageVO sendMessageVO = orderBasicInfoService.selectOrderInfoByOrderCode(dto.getOrderCode());
2024-02-28 15:22:38 +08:00
if (Objects.isNull(sendMessageVO)) {
log.error("停止充电发送消息, 通过orderCode:{}, 查询SendMessageVO为null", dto.getOrderCode());
return null;
}
2023-03-04 16:29:55 +08:00
msgInfo.setType("2"); // 2-结束充电推送消息
msgInfo.setTouser(sendMessageVO.getOpenId());
// 封装对象并调用发送消息的方法
AppletTemplateMessageSendDTO.StopChargingMessage stopChargingMessage = new AppletTemplateMessageSendDTO.StopChargingMessage();
msgInfo.setStopChargingMessage(stopChargingMessage);
BigDecimal orderAmount = new BigDecimal(sendMessageVO.getOrderAmount());
BigDecimal discountAmount = new BigDecimal(sendMessageVO.getDiscountAmount());
stopChargingMessage.setChargingAmount(String.valueOf(orderAmount.subtract(discountAmount))); // 订单金额 2024.03.05改为 实付金额
stopChargingMessage.setEndReason(sendMessageVO.getStopReason()); // 结束原因
stopChargingMessage.setOrderCode(sendMessageVO.getOrderCode()); // 订单号
stopChargingMessage.setChargingDegree(sendMessageVO.getChargingDegree()); // 充电度数
String chargingTime = "";
if (StringUtils.isNotBlank(sendMessageVO.getChargeStartTime()) && StringUtils.isNotBlank(sendMessageVO.getChargeStopTime())) {
Date chargeStartTime = DateUtils.parseDate(sendMessageVO.getChargeStartTime(), DateUtils.YYYY_MM_DD_HH_MM_SS);
Date chargeStopTime = DateUtils.parseDate(sendMessageVO.getChargeStopTime(), DateUtils.YYYY_MM_DD_HH_MM_SS);
chargingTime = DateUtils.getDatePoor(chargeStopTime, chargeStartTime);
}
stopChargingMessage.setChargingTime(chargingTime); // 充电时长
2024-08-05 15:46:59 +08:00
return uniAppSendMsg(msgInfo); // 停止充电
2023-03-04 16:29:55 +08:00
}
/**
* 预约充电结果小程序服务通知
*/
2024-08-05 15:46:59 +08:00
public Map<String, String> reservationStartupResultSendMsg(String openId, String startTime, String endTime, String startUpResult, String failReason) {
AppletTemplateMessageSendDTO msgInfo = new AppletTemplateMessageSendDTO();
2024-08-23 10:37:08 +08:00
msgInfo.setType(Constants.THREE); // 2-结束充电推送消息
2024-08-05 15:46:59 +08:00
msgInfo.setTouser(openId);
// 封装对象并调用发送消息的方法
AppletTemplateMessageSendDTO.StartUpResultMessage startUpResultMessage = new AppletTemplateMessageSendDTO.StartUpResultMessage();
startUpResultMessage.setStartTime(startTime);
startUpResultMessage.setEndTime(endTime);
startUpResultMessage.setStartUpResult(startUpResult);
startUpResultMessage.setFailReason(failReason);
msgInfo.setStartUpResultMessage(startUpResultMessage);
return uniAppSendMsg(msgInfo); // 预约充电结果
}
/**
* 小程序发送消息方法/小程序通知/服务通知
2023-03-04 16:29:55 +08:00
* @param dto
* @return
*/
private Map<String, String> uniAppSendMsg(AppletTemplateMessageSendDTO dto) {
// 判断是什么场景调用此方法1-开始充电推送消息2-充电结束推送消息)
String type = dto.getType();
// 根据不同的场景set不同的对象
2024-08-23 10:40:16 +08:00
Map<String, Object> map = Maps.newHashMap();
String templateId = null;
2023-03-04 16:29:55 +08:00
if (StringUtils.equals("1", type)) {
// 开始充电
2024-08-23 10:40:16 +08:00
templateId = startChargingTmpId;
2023-03-04 16:29:55 +08:00
map.put("thing5", ImmutableMap.of("value", dto.getStartChargingMessage().getStationName())); // 充电站名称
map.put("time2", ImmutableMap.of("value", dto.getStartChargingMessage().getStartTime())); // 开始时间
map.put("character_string11", ImmutableMap.of("value", dto.getStartChargingMessage().getOrderCode())); // 订单编号
map.put("thing7", ImmutableMap.of("value", dto.getStartChargingMessage().getPileConnectorCode())); // 充电插座
map.put("thing13", ImmutableMap.of("value", dto.getStartChargingMessage().getTotalPrice())); // 收费标准
2023-03-04 16:29:55 +08:00
} else if (StringUtils.equals("2", type)) {
// 结束充电
2024-08-23 10:40:16 +08:00
templateId = stopChargingTmpId;
map.put("character_string5", ImmutableMap.of("value", dto.getStopChargingMessage().getOrderCode())); // 充电金额
2023-03-04 16:29:55 +08:00
map.put("amount17", ImmutableMap.of("value", dto.getStopChargingMessage().getChargingAmount())); // 充电金额
map.put("thing7", ImmutableMap.of("value", dto.getStopChargingMessage().getEndReason())); // 结束原因
map.put("thing22", ImmutableMap.of("value", dto.getStopChargingMessage().getChargingTime())); // 充电时长
map.put("number13", ImmutableMap.of("value", dto.getStopChargingMessage().getChargingDegree())); // 充电度数
2024-08-05 15:46:59 +08:00
} else if (StringUtils.equals("3", type)) {
2024-08-23 10:37:08 +08:00
// 预约充电启动通知
2024-08-23 10:40:16 +08:00
templateId = stopChargingTmpId;
2024-08-05 15:46:59 +08:00
map.put("time2", ImmutableMap.of("value", dto.getStartUpResultMessage().getStartTime())); // 开始时间
map.put("time3", ImmutableMap.of("value", dto.getStartUpResultMessage().getEndTime())); // 结束时间
map.put("phrase20", ImmutableMap.of("value", dto.getStartUpResultMessage().getStartUpResult())); // 启动结果
map.put("thing21", ImmutableMap.of("value", dto.getStartUpResultMessage().getFailReason())); // 失败原因
2023-03-04 16:29:55 +08:00
}
2024-08-23 10:40:16 +08:00
dto.setTemplate_id(templateId);
dto.setData(map);
2023-03-04 16:29:55 +08:00
// 调用下面的发送消息接口
return uniformMessageSend(dto);
}
/**
* 同一消息发送接口
* AppletTemplateMessageSendDTO 是一个传输类
*/
public Map<String, String> uniformMessageSend(AppletTemplateMessageSendDTO data) {
String token = getAccessToken();
// 调用发型接口
String url = WX_APPLET_URl + "/message/subscribe/send?access_token=" + token;
String returnData = HttpUtils.sendPost(url, JSON.toJSONString(data));
Map<String, Object> map = null;
try {
map = objectMapper.readValue(returnData, Map.class);
} catch (IOException e) {
log.error("小程序异常通知-同一消息发送-转化异常", e);
}
String errcode = String.valueOf(map.get("errcode"));
String errmsg = String.valueOf(map.get("errmsg"));
if (!errcode.equals(Constants.ZERO)) {
2023-11-27 14:53:24 +08:00
log.error("消息发送失败code:" + errcode + ", msg:" + errmsg);
2023-03-04 16:29:55 +08:00
}
Map<String, String> resultMap = new HashMap<>();
resultMap.put("code", errcode);
resultMap.put("message", errmsg);
return resultMap;
}
}