在用户购买会员卡后的第二天下午四点发送微信模板消息
在pom.xml里面配置
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>${wexin-tools-version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>${wexin-tools-version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>${wexin-tools-version}</version>
</dependency>
所以先在数据库里面建了一张表,把发送时间写进去,把微信模板中要用到的信息存入到数据库中,并设置一个标识去标识这个用户有没有被发送过消息。然后写个定时任务,每隔一定时间去把这个时间拿出来跟当前时间作比较,当前时间大于存在数据库里的时间就执行发送模板消息,然后把标识改成1。
这里面的OPENID都是公众号的openid,不是小程序的openid.可以根据小程序的unionID去找到用户在公众号中的openid
package com.umshuo.service;
import com.aliyun.openservices.shade.com.alibaba.fastjson.JSON;
import com.aliyun.openservices.shade.com.alibaba.fastjson.JSONObject;
import com.qiniu.util.StringUtils;
import com.umshuo.domain.Business;
import com.umshuo.domain.Receiver;
import com.umshuo.domain.User;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Slf4j
@Service
public class SyncOpenIdService {
@Autowired
@Qualifier("wxMpService")
private WxMpService wxMpService;
@Autowired
@Qualifier("wxMpServiceBusiness")
private WxMpService wxMpServiceBusiness;
@Autowired
private UserService userService;
@Autowired
private ReceiverService receiverService;
@Autowired
private BusinessService businessService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void syncFromWechat(String lastOpenId){
try {
log.info("同步关注微信公众号社区买手的用户信息 - lastMpOpenId: [{}]", lastOpenId);
WxMpUserList list = getWxMpUserList(lastOpenId);
log.info("获取的用户数量: " + list.getOpenids().size());
List<Map<String,Object>> userList = userService.selectUnionList();
int count=0;
// 判断是否有新关注用户
if (list != null && list.getOpenids().size() > 0 && userList!=null && userList.size()>0) {
for (String openid : list.getOpenids()) {
WxMpUser wxUser = wxMpService.getUserService().userInfo(openid);
// log.debug("获取用户信息: openId:[{}], wxUser:[{}]", openid, JSON.toJSONString(wxUser));
boolean result = updateUser(userList,wxUser.getUnionId(),wxUser.getOpenId());
if(result){
count++;
log.info("更新的用户信息- openId:{},UnionId:{}", wxUser.getOpenId(),wxUser.getUnionId());
}
// if (result != true) {
// // 更新用户公众号openId失败, 将用户信息暂存redis
// //log.info("用户信息不存在,临时存储到redis - openId:[{}]", openid);
// //redisTemplate.opsForValue().set("wx_syncuser_" + wxUser.getUnionId(), JSON.toJSONString(wxUser));
// }
}
//redisTemplate.opsForValue().set("lastMpOpenId", list.getOpenids().get(list.getOpenids().size() - 1));
}
log.info("----更新关注社区买手微信公众号openid的用户数:"+count);
} catch (Exception ex) {
log.error(ex.getMessage());
ex.printStackTrace();
}
}
/**
* 同步旗手和商户的微信openID
* @param lastOpenId
*/
public void syncBusinessFromWechat(String lastOpenId){
try {
log.info("同步关注社区达微信公众号的用户信息 - lastMpOpenId: [{}]", lastOpenId);
WxMpUserList list = getWxMpBusinessUserList(lastOpenId);
log.info("获取的用户数量: " + list.getOpenids().size());
List<Map<String,Object>> busiList = businessService.selectUnionList();
List<Map<String,Object>> recieveList = receiverService.selectUnionList();
int count=0;
// 判断是否有新关注用户
if (list != null && list.getOpenids().size() > 0 && ((busiList!=null && busiList.size()>0)||(recieveList!=null && recieveList.size()>0))) {
boolean result = false;
for (String openid : list.getOpenids()) {
WxMpUser wxUser = wxMpServiceBusiness.getUserService().userInfo(openid);
result = updateBusiUser(busiList,wxUser.getUnionId(),wxUser.getOpenId());
if(result){
count++;
log.info("更新商户openID信息- openId:{},UnionId:{}", wxUser.getOpenId(),wxUser.getUnionId());
}
result = updateRecieveUser(recieveList,wxUser.getUnionId(),wxUser.getOpenId());
if(result){
count++;
log.info("更新骑手openID信息- openId:{},UnionId:{}", wxUser.getOpenId(),wxUser.getUnionId());
}
}
}
log.info("----更新社区达微信公众号openid的用户数:"+count);
} catch (Exception ex) {
log.error(ex.getMessage());
ex.printStackTrace();
}
}
/**
* 更新用户微信公众号openId
* @return
*/
public boolean updateUser(List<Map<String,Object>> userList,String unionId, String openId) {
// 查询到用户信息, 更新用户公众号openId
if (openId!=null && unionId!=null) {
for (Map<String,Object> map:userList) {
if(map.get("unionId").equals(unionId)){
if(map.get("wxOpenId")==null || !openId.equals(map.get("wxOpenId"))){
User user = new User();
user.setId((Long)map.get("id"));
user.setWxOpenId(openId);
int reu = userService.updateUser(user);
if(reu>0) return true;
}
break;
}
}
}
return false;
}
/**
* 更新商户微信公众号openId
* @return
*/
public boolean updateBusiUser(List<Map<String,Object>> busiList,String unionId, String openId){
// 查询到商户信息表, 更新用户公众号openId
if (openId!=null && unionId!=null) {
for (Map<String,Object> map:busiList) {
if(map.get("unionId").equals(unionId)){
if(map.get("wxOpenId")==null || !openId.equals(map.get("wxOpenId"))){
Business business = new Business();
business.setId((Long)map.get("id"));
business.setWxOpenId(openId);
int reu = businessService.updateBusiness(business);
if(reu>0) return true;
}
break;
}
}
}
return false;
}
/**
* 更新商户微信公众号openId
* @return
*/
public boolean updateRecieveUser(List<Map<String,Object>> reviList,String unionId, String openId){
//更新骑手表公众号openId
if (openId!=null && unionId!=null) {
for (Map<String,Object> map:reviList) {
if(map.get("unionId").equals(unionId)){
if(map.get("wxOpenId")==null || !openId.equals(map.get("wxOpenId"))){
Receiver receiver = new Receiver();
receiver.setId((Long)map.get("id"));
receiver.setWxOpenId(openId);
int reu = receiverService.updateReceiver(receiver);
if(reu>0) return true;
}
break;
}
}
}
return false;
}
/**
* 获取微信公众号关注用户列表
*
* @param lastOpenId
* @return
* @throws WxErrorException
*/
private WxMpUserList getWxMpUserList(String lastOpenId) throws WxErrorException {
return wxMpService.getUserService().userList(lastOpenId);
}
/**
* 获取微信公众号关注用户列表
*
* @param lastOpenId
* @return
* @throws WxErrorException
*/
private WxMpUserList getWxMpBusinessUserList(String lastOpenId) throws WxErrorException {
return wxMpServiceBusiness.getUserService().userList(lastOpenId);
}
}
定时任务:
第一个:
2.
WechatMpConfig
package com.umshuo.properties;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class WechatMpConfig {
@Autowired
WechatAccountConfig wechatAccountConfig;
/**
* 微信服务装载
* @return
*/
@Bean
public WxMpService wxMpService() {
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
/**
* 微信服务装载
* @return
*/
@Bean
public WxMpService wxMpServiceBusiness() {
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxMpConfigStorageBusiness());
return wxMpService;
}
/**
* 配置温馨的APPID和密码
* @return
*/
@Bean
public WxMpConfigStorage wxMpConfigStorage() {
WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
wxMpConfigStorage.setAppId(wechatAccountConfig.getAppId());
wxMpConfigStorage.setSecret(wechatAccountConfig.getSecret());
return wxMpConfigStorage;
}
/**
* 配置温馨的APPID和密码
* @return
*/
@Bean
public WxMpConfigStorage wxMpConfigStorageBusiness() {
WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
wxMpConfigStorage.setAppId(wechatAccountConfig.getAppIdBusiness());
wxMpConfigStorage.setSecret(wechatAccountConfig.getSecretBusiness());
return wxMpConfigStorage;
}
}
3.
WxMpProperties
package com.umshuo.properties;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "wechat.mp")
public class WxMpProperties {
/**
* 设置微信公众号的appid
*/
private String appId;
/**
* 设置微信公众号的app secret
*/
private String secret;
/**
* 设置微信公众号的token
*/
private String token;
/**
* 设置微信公众号的EncodingAESKey
*/
private String aesKey;
public String getAppId() {
return this.appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getSecret() {
return this.secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
}
public String getAesKey() {
return this.aesKey;
}
public void setAesKey(String aesKey) {
this.aesKey = aesKey;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}
wxservice:
package com.umshuo.service;
import com.alibaba.fastjson.JSON;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.umshuo.common.JsonUtil;
import com.umshuo.common.ServerResponse;
import com.umshuo.common.StringUtil;
import com.umshuo.common.WXBizDataCrypt;
import com.umshuo.properties.WechatAccountConfig;
import com.umshuo.properties.WechatMpConfig;
import com.umshuo.vo.SessionKeyVo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* @author chezhu.xin
*/
@Slf4j
@Service
public class WxService {
@Autowired
@Qualifier("wxMpService")
private WxMpService mpService;
@Autowired
@Qualifier("wxMpServiceBusiness")
private WxMpService wxMpServiceBusiness;
@Autowired
private WechatAccountConfig wechatAccountConfig;
private static final Cache<String, String> CACHE = CacheBuilder.newBuilder()
.initialCapacity(1000)
.maximumSize(20000)
.expireAfterWrite(30, TimeUnit.MINUTES)
.build();
private static final Cache<String, String> OPENID_CACHE = CacheBuilder.newBuilder()
.initialCapacity(1000)
.maximumSize(20000)
.expireAfterWrite(30, TimeUnit.MINUTES)
.build();
@Getter
private enum WxAppIdEnum {
/**
* 微信小程序信息
*/
APP_1("小程序名字", "这里放APPID", "这里放模板id"),
APP_2("小程序名字", "这里放APPID", "这里放模板id"),
APP_3("小程序名字", "这里放APPID", "这里放模板id");
private final String desc;
private final String appId;
private final String appSecret;
WxAppIdEnum(String desc, String appId, String appSecret) {
this.desc = desc;
this.appId = appId;
this.appSecret = appSecret;
}
public static WxAppIdEnum getWxAppIdEnum(String appId) {
for (WxAppIdEnum wxAppIdEnum : Lists.newArrayList(WxAppIdEnum.values())) {
if (Objects.equals(appId, wxAppIdEnum.getAppId())) {
return wxAppIdEnum;
}
}
return null;
}
}
public ServerResponse<SessionKeyVo> sessionKey(String code, String appId) throws JSONException {
WxAppIdEnum wxAppIdEnum = WxAppIdEnum.getWxAppIdEnum(appId);
if (wxAppIdEnum == null) {
return ServerResponse.createByErrorMessage(appId);
}
String requestAppId = wxAppIdEnum.appId;
String requestAppSecret = wxAppIdEnum.appSecret;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("https://api.weixin.qq.com/sns/jscode2session");
stringBuilder.append("?").append("appid").append("=").append(requestAppId);
stringBuilder.append("&").append("secret").append("=").append(requestAppSecret);
stringBuilder.append("&").append("js_code").append("=").append(code);
stringBuilder.append("&").append("grant_type").append("=").append("authorization_code");
String result = new RestTemplate().getForObject(stringBuilder.toString(), String.class);
log.debug(stringBuilder.toString());
log.debug(result);
String sessinKey = JsonUtil.toJsonObject(result).getString("session_key");
String openid = JsonUtil.toJsonObject(result).getString("openid");
log.debug("添加缓存=="+openid);
CACHE.put(code, sessinKey);
OPENID_CACHE.put(code, openid);
SessionKeyVo sessionKeyVo = JsonUtil.fromJson(result, SessionKeyVo.class);
return ServerResponse.createBySuccess(sessionKeyVo);
}
public ServerResponse<SessionKeyVo> descrypt(String code, String appId, String encryptedData, String iv) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, JSONException {
if (StringUtil.isBlank(code)) {
return ServerResponse.createByErrorMessage("code 值不允许为空");
}
String sessionKey = CACHE.getIfPresent(code);
if (StringUtil.isBlank(sessionKey)) {
WxAppIdEnum wxAppIdEnum = WxAppIdEnum.getWxAppIdEnum(appId);
if (wxAppIdEnum == null) {
return ServerResponse.createByErrorMessage(appId);
}
String requestAppId = wxAppIdEnum.appId;
String requestAppSecret = wxAppIdEnum.appSecret;
String stringBuilder = "https://api.weixin.qq.com/sns/jscode2session" +
"?" + "appid" + "=" + requestAppId +
"&" + "secret" + "=" + requestAppSecret +
"&" + "js_code" + "=" + code +
"&" + "grant_type" + "=" + "authorization_code";
String resultStr = new RestTemplate().getForObject(stringBuilder, String.class);
String str = JsonUtil.toJsonObject(resultStr).getString("session_key");
String openid = JsonUtil.toJsonObject(resultStr).getString("openid");
if (StringUtil.isNotBlank(str)) {
sessionKey = str;
CACHE.put(appId,sessionKey);
}
log.debug("查询的结果:{}",resultStr);
if(StringUtil.isNotBlank(resultStr)){
SessionKeyVo sessionKeyVo = JsonUtil.fromJson(resultStr, SessionKeyVo.class);
return ServerResponse.createBySuccess(sessionKeyVo);
}
}
String result = WXBizDataCrypt.getInstance().decrypt(encryptedData, sessionKey, iv, "utf-8");
log.debug("result:{}", result);
SessionKeyVo sessionKeyVo = JsonUtil.fromJson(result, SessionKeyVo.class);
return ServerResponse.createBySuccess(sessionKeyVo);
}
/**
* 解密unionID
*/
public String descrypt(String sessionKey, String encryptedData, String iv) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
String result = WXBizDataCrypt.getInstance().decrypt(encryptedData, sessionKey, iv, "utf-8");
log.debug("result:{}", result);
SessionKeyVo sessionKeyVo = JsonUtil.fromJson(result, SessionKeyVo.class);
return sessionKeyVo.getUnionid();
}
/**
* 发送社区买手模板消息
* @param templateMap
* @return
*/
public boolean sendMessage(Map<String,Object> templateMap) {
try {
WxMpTemplateMessage template = new WxMpTemplateMessage();
template.setToUser((String)templateMap.get("openId"));
template.setTemplateId((String)templateMap.get("templateId"));
template.setMiniProgram(new WxMpTemplateMessage.MiniProgram(wechatAccountConfig.getMiniAppId(),(String)templateMap.get("url")));
template.setData((List<WxMpTemplateData>)templateMap.get("data"));
String response = mpService.getTemplateMsgService().sendTemplateMsg(template);
log.debug("发送微信模板信息结果 - openId:[{}], response:[{}]", template.getToUser(), JSON.toJSONString(response));
return true;
} catch (WxErrorException ex) {
ex.printStackTrace();
log.error("【微信模版消息】发送失败, {}", ex);
}
return false;
}
/**
*
*/
/**
* 发送社区达模板消息
* @param templateMap
* @return
*/
public boolean sendMessageBusiness(Map<String,Object> templateMap) {
try {
WxMpTemplateMessage template = new WxMpTemplateMessage();
template.setToUser((String)templateMap.get("openId"));
template.setTemplateId((String)templateMap.get("templateId"));
template.setMiniProgram(new WxMpTemplateMessage.MiniProgram(wechatAccountConfig.getMiniAppIdBusiness(),(String)templateMap.get("url")));
template.setData((List<WxMpTemplateData>)templateMap.get("data"));
String response = wxMpServiceBusiness.getTemplateMsgService().sendTemplateMsg(template);
log.debug("发送微信模板信息结果 - openId:[{}], response:[{}]", template.getToUser(), JSON.toJSONString(response));
return true;
} catch (WxErrorException ex) {
ex.printStackTrace();
log.error("【微信模版消息】发送失败, {}", ex);
}
return false;
}
}