首先我们需要订阅一个消息:
订阅教程本文章并未提起,感兴趣的同学自行百度。
我们可以看到订阅消息中【消息内容】有很多参数,我们在发送消息时就需要将这些参数进行填充,当然填充的时候要注意格式,如果格式不对还是会报错。
教程开始:
1、创建一个实体类,用来填充对应的数据
import lombok.Data;
import java.util.Date;
@Data
public class LeaveResultMsg {
/**
* 请假结果通知 -- 模板ID
*/
public static String RESULTID = "Qd0*************T8k";
/**
* 请假人OpenId
*/
private String openId;
/**
* 请假人名称
*/
private String name;
/**
* 请假开始时间
*/
private Date startTime;
/**
* 请假结束时间
*/
private Date endTime;
/**
* 审核人
*/
private String examine;
/**
* 请假结果(同意,不同意)
*/
private String status;
/**
* 请假类型
*/
private String type;
}
2、实现类
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import org.dromara.common.api.service.ApiWeChatUtilsService;
import org.dromara.common.api.utils.DateUtil;
import org.dromara.school.domain.LeaveResultMsg;
import org.dromara.school.service.ISubscribeMsgService;
import org.dromara.system.service.ISysConfigService;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Service
@RequiredArgsConstructor
public class SubscribeMsgService implements ISubscribeMsgService {
private final static String SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
// private final WeChatTokenUtil weChatTokenUtil;
private final ISysConfigService configService;
private final ApiWeChatUtilsService apiWeChatUtilsService;
/**
* 请假结果通知
* @param msg
* @throws Exception
*/
public void leaveResultW(LeaveResultMsg msg){
try {
System.out.println(msg.toString());
Map<String, Object> params = baseParams(msg.getOpenId());
params.put("template_id", LeaveResultMsg.RESULTID);
Map<String, Object> data = new HashMap<String, Object>();
// 传入转换后的 UTF-8 编码字节数组
data.put("thing2", Collections.singletonMap("value", new String(msg.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)));
data.put("time3", Collections.singletonMap("value", DateUtil.getStringDateFormat(msg.getStartTime())));
data.put("time4",Collections.singletonMap("value", DateUtil.getStringDateFormat(msg.getEndTime())));
data.put("thing7", Collections.singletonMap("value",new String(msg.getExamine().getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)));
data.put("phrase1",Collections.singletonMap("value", new String(msg.getStatus().getBytes(StandardCharsets.UTF_8),StandardCharsets.UTF_8)));
params.put("data", data);
System.err.println(params);
String post;
try {
post = HttpUtil.post(SEND_URL + apiWeChatUtilsService.getAccessTokenByRedis(0), JSONUtil.toJsonStr(params));
}catch (Exception e) {
post = HttpUtil.post(SEND_URL + apiWeChatUtilsService.getAccessTokenByRedis(1), JSONUtil.toJsonStr(params));
}
// String post = HttpUtil.post(SEND_URL + weChatTokenUtil.getAccessToken(), JSONUtil.toJsonStr(params));
System.err.println(post);
}catch (Exception e){
e.printStackTrace();
}
}
}
关联到的其他方法:
3、组装参数
@Service
@RequiredArgsConstructor
public class SubscribeMsgService implements ISubscribeMsgService {
/**
* 组装基础参数
*
* @param openId
* @return
*/
private Map<String, Object> baseParams(String openId) {
Map<String, Object> map = new HashMap<String, Object>();
String touser = openId;
String page = "/pages/home/index";
// 微信-小程序订阅跳转版本,developer:开发版,trial:体验版,formal:正式版
String miniprogramState = configService.selectConfigByKey("***.version"); //小程序版本
map.put("touser", touser);
map.put("page", page);
map.put("miniprogram_state", miniprogramState);
return map;
}
}
4、时间转换
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class DateUtil {
/**
* 获取当前时间,转换成String(yyyy-MM-dd HH:mm:ss)
* @return yyyyMMddHHmmss
*/
public static String getStringDateFormat(Date date){
//Thu May 11 11:08:15 GMT+08:00 2023
//设置日期格式
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//获取String类型的时间
String str = df.format(date);
return str;
}
}
5、获取token
package org.dromara.system.dubbo;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.api.service.ApiWeChatUtilsService;
import org.dromara.common.api.utils.StringUtil;
import org.dromara.common.api.utils.https.HttpClientUtil;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.base.BaseException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* 字典 业务层处理
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class ApiWeChatUtilsServiceImpl implements ApiWeChatUtilsService {
@Autowired
ISysConfigService sysConfigService;
/**
* 0正常获取,1可能token失效了,重新获取(线上线下冲突)
* @return
*/
@Override
public String getAccessTokenByRedis(int state) {
String key = "wx.access_token";
String accessToken;
if (state==0){
accessToken = RedisUtils.getCacheObject(key);
if (StringUtil.isEmpty(accessToken)) {
accessToken = getAccessTokenByAddress();
if (!StringUtil.isEmpty(accessToken))
RedisUtils.setCacheObject(key, accessToken, Duration.ofMinutes(120));
}
}else {
accessToken = getAccessTokenByAddress();
if (!StringUtil.isEmpty(accessToken))
RedisUtils.setCacheObject(key, accessToken, Duration.ofMinutes(120));
}
return accessToken;
}
private String getAccessTokenByAddress() {
String appid = sysConfigService.selectConfigByKey("***.appid");
String secret =sysConfigService.selectConfigByKey("***.secret");
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
String result = HttpUtil.get(url);
HashMap<String, String> resultMap = (HashMap<String, String>) JSONUtil.parse(result).toBean(HashMap.class);
String accessToken = resultMap.get("access_token");
if (StringUtil.isEmpty(accessToken))
throw new BaseException(resultMap.get("errmsg"));
return accessToken;
}
/**
* 获取手机号
* @param code
* @return
*/
@Override
public String getPhoneByCode(String code) {
String accessToken = getAccessTokenByRedis(0);
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
HttpHeaders headers = new HttpHeaders();
RestTemplate restTemplate = new RestTemplate();
HttpEntity<Map<String, String>> httpEntity;
if (code.contains("code")) {
httpEntity = new HttpEntity(code,headers);
}else {
Map<String, String> params = new HashMap<>();
params.put("code", code);
httpEntity = new HttpEntity(params,headers);
}
ResponseEntity<Object> response = restTemplate.postForEntity(url, httpEntity, Object.class, new Object[0]);
HashMap<String, Object> resultMap = (HashMap<String, Object>) JSONUtil.parse(response.getBody()).toBean(HashMap.class);
int errcode = ((Integer) resultMap.get("errcode")).intValue();
if (errcode != 0) {
if (errcode == 40001){
//可能会出现多个服务器重复获取,导致accessToken失效的情况
accessToken = getAccessTokenByRedis(1);
url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
response = restTemplate.postForEntity(url, httpEntity, Object.class, new Object[0]);
resultMap = (HashMap<String, Object>) JSONUtil.parse(response.getBody()).toBean(HashMap.class);
errcode = ((Integer) resultMap.get("errcode")).intValue();
if (errcode != 0){
throw new ServiceException("获取手机号出错,报错类型------>{}",errcode);
}
}else {
throw new ServiceException("获取手机号出错,报错类型------>{}",errcode);
}
}
HashMap<String, Object> phoneInfo = (HashMap<String, Object>) JSONUtil.parse(resultMap.get("phone_info")).toBean(HashMap.class);
String phone = (String) phoneInfo.get("purePhoneNumber");
return phone;
}
/**
* 获取手机号2
* @param code
* @return
*/
public String getPhoneByCode2(String code) {
String accessToken = getAccessTokenByRedis(0);
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
// String jsonStr = "{\"code\":\"" + code + "\"}";
String httpOrgCreateTestRtn = HttpClientUtil.doPost(url, code, "utf-8");
System.out.println("获取到的手机号----------->"+httpOrgCreateTestRtn);
return httpOrgCreateTestRtn;
}
/**
* 获取openid
* @param code
* @return
*/
@Override
public String getOpenidByCode(String code) {
String appid = sysConfigService.selectConfigByKey("weChat.mini.appid");
String secret =sysConfigService.selectConfigByKey("weChat.mini.secret");
//https://api.weixin.qq.com/sns/jscode2session
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret +
"&js_code=" + code + "&grant_type=authorization_code";
String result = HttpUtil.get(url);
HashMap<String, String> resultMap = (HashMap<String, String>) JSONUtil.parse(result).toBean(HashMap.class);
String openId = resultMap.get("openid");
// System.out.println("获取到的openId----------->"+openId);
if (StringUtils.isNotEmpty(openId)) {
return openId;
} else {
throw new ServiceException("用户信息获取错误,请稍候重试",Integer.valueOf(resultMap.get("errcode")) );
}
}
}
以上用到的config类是配置类,配置的内容是由你申请小程序时候得到的数据。