|
|
@ -2,24 +2,38 @@ package com.elink.esua.epdc.service.impl; |
|
|
|
|
|
|
|
import cn.binarywang.wx.miniapp.bean.WxMaTemplateData; |
|
|
|
import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; |
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
import com.elink.esua.epdc.commons.tools.exception.RenException; |
|
|
|
import com.elink.esua.epdc.commons.tools.redis.RedisKeys; |
|
|
|
import com.elink.esua.epdc.commons.tools.redis.RedisUtils; |
|
|
|
import com.elink.esua.epdc.commons.tools.utils.Result; |
|
|
|
import com.elink.esua.epdc.dto.TemplateData; |
|
|
|
import com.elink.esua.epdc.dto.epdc.form.EpdcDeleteWxFormIdFormDTO; |
|
|
|
import com.elink.esua.epdc.dto.epdc.result.EpdcUserRegisterAuditMsgResultDTO; |
|
|
|
import com.elink.esua.epdc.dto.epdc.result.UserWorkAndAnalyOpenIdDTO; |
|
|
|
import com.elink.esua.epdc.dto.form.SendMessageFormDTO; |
|
|
|
import com.elink.esua.epdc.enums.AppUserAuditStateEnum; |
|
|
|
import com.elink.esua.epdc.feign.AdminFeignClient; |
|
|
|
import com.elink.esua.epdc.feign.MessageFeignClient; |
|
|
|
import com.elink.esua.epdc.feign.UserFeignClient; |
|
|
|
import com.elink.esua.epdc.service.MessageService; |
|
|
|
import com.elink.esua.epdc.utils.WxMaServiceUtils; |
|
|
|
import com.elink.esua.epdc.utils.WxSendMessageUtils; |
|
|
|
import com.google.common.collect.Lists; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import me.chanjar.weixin.common.error.WxErrorException; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.*; |
|
|
|
import java.util.concurrent.Callable; |
|
|
|
import java.util.concurrent.ExecutorService; |
|
|
|
import java.util.concurrent.Executors; |
|
|
|
import java.util.concurrent.Future; |
|
|
|
import java.util.concurrent.atomic.AtomicInteger; |
|
|
|
|
|
|
|
/** |
|
|
|
* @author yujintao |
|
|
@ -36,12 +50,47 @@ public class MessageServiceImpl implements MessageService { |
|
|
|
@Autowired |
|
|
|
private UserFeignClient userFeignClient; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private AdminFeignClient adminFeignClient; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private WxMaServiceUtils wxMaServiceUtils; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private RedisUtils redisUtils; |
|
|
|
|
|
|
|
@Value("${wx.message.analysisAppId}") |
|
|
|
private String analysisAppId; |
|
|
|
|
|
|
|
@Value("${wx.message.analysisSecret}") |
|
|
|
private String analysisSecret; |
|
|
|
|
|
|
|
@Value("${wx.message.analysisTemplate}") |
|
|
|
private String analysisTemplate; |
|
|
|
|
|
|
|
@Value("${wx.message.workAppId}") |
|
|
|
private String workAppId; |
|
|
|
|
|
|
|
@Value("${wx.message.workSecret}") |
|
|
|
private String workSecret; |
|
|
|
|
|
|
|
@Value("${wx.message.workTemplate}") |
|
|
|
private String workTemplate; |
|
|
|
|
|
|
|
@Value("${wx.message.jumpType}") |
|
|
|
private String jumpType; |
|
|
|
|
|
|
|
@Value("${wx.message.page}") |
|
|
|
private String page; |
|
|
|
|
|
|
|
@Value("${wx.message.url}") |
|
|
|
private String url; |
|
|
|
|
|
|
|
@Value("${wx.message.lang}") |
|
|
|
private String lang; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 注册审核失败服务消息模版 |
|
|
|
*/ |
|
|
@ -57,6 +106,9 @@ public class MessageServiceImpl implements MessageService { |
|
|
|
*/ |
|
|
|
private static String MA_PAGE = "pages/index/index"; |
|
|
|
|
|
|
|
//创建固定大小为100 的线程池
|
|
|
|
private static ExecutorService threadPool = Executors.newFixedThreadPool(100); |
|
|
|
|
|
|
|
/** |
|
|
|
* 发送六位短信验证码 |
|
|
|
* |
|
|
@ -141,4 +193,141 @@ public class MessageServiceImpl implements MessageService { |
|
|
|
return new Result(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 小程序消息推送demo |
|
|
|
* |
|
|
|
* @return com.elink.esua.epdc.commons.tools.utils.Result |
|
|
|
* @author wanggonfeng |
|
|
|
* @date 2020/05/26 14:18 |
|
|
|
*/ |
|
|
|
public Result sendMessage() { |
|
|
|
// 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
|
|
|
|
String miniprogram_state = "trial"; |
|
|
|
// 模板ID
|
|
|
|
String template_id = "wagGg4eAeHu1N2N0o8Vhyan41Gr3DqFBD81o5Lv7XnQ"; |
|
|
|
// 用户openID oZCeb5TZc2oBwT4jHb0kDmQsN0Xw
|
|
|
|
String openId = "oZCeb5TZc2oBwT4jHb0kDmQsN0Xw";//os3585flOvphXsb7XNmYOZtooEro oZCeb5W6GEUCVHG3InnPv1Q6r0f0
|
|
|
|
// 小程序跳转页
|
|
|
|
String page = "pages/index/index"; |
|
|
|
// 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
|
|
|
|
String lang = "zh_CN"; |
|
|
|
|
|
|
|
// 获取access_token
|
|
|
|
String access_token = WxSendMessageUtils.getAccess_token(analysisAppId, analysisSecret); |
|
|
|
// 拼接URL
|
|
|
|
String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + access_token; |
|
|
|
|
|
|
|
// 配置模板内容
|
|
|
|
Map<String, TemplateData> m = new HashMap<>(5); |
|
|
|
TemplateData keyword1 = new TemplateData(); |
|
|
|
keyword1.setValue("您有新的话题,请登录小程序查看!"); |
|
|
|
m.put("thing1", keyword1); |
|
|
|
TemplateData keyword2 = new TemplateData(); |
|
|
|
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
|
|
|
String dateStr = sdf.format(new Date()); |
|
|
|
keyword2.setValue(dateStr); |
|
|
|
m.put("time2", keyword2); |
|
|
|
|
|
|
|
String resultMsg = WxSendMessageUtils.sendMessageByOpenId(openId,url,miniprogram_state,template_id,m,lang,page); |
|
|
|
|
|
|
|
return new Result().ok(resultMsg); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public Result sendMessage(SendMessageFormDTO formDto) { |
|
|
|
|
|
|
|
// 模板ID
|
|
|
|
String value = ""; |
|
|
|
if(1 == formDto.getType()){ |
|
|
|
//通知
|
|
|
|
value = "您有新的通知,请登录小程序查看!"; |
|
|
|
}else if(2 == formDto.getType()){ |
|
|
|
//话题
|
|
|
|
value = "您有新的话题,请登录小程序查看!"; |
|
|
|
}else{ |
|
|
|
throw new RenException("消息推送类型错误!"); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取openID
|
|
|
|
Result<UserWorkAndAnalyOpenIdDTO> userIdsResult = adminFeignClient.userRelationWorkAndAnalyOpenId(); |
|
|
|
if(userIdsResult == null || userIdsResult.getData() == null){ |
|
|
|
return new Result().error("获取openid失败!"); |
|
|
|
} |
|
|
|
|
|
|
|
// 调用获取openid接口
|
|
|
|
UserWorkAndAnalyOpenIdDTO userWorkAndAnalyOpenIdDTO = userIdsResult.getData(); |
|
|
|
List<String> analyOpenIdList = userWorkAndAnalyOpenIdDTO.getAnalyOpenIds(); |
|
|
|
List<String> workOpenIdList = userWorkAndAnalyOpenIdDTO.getWorkOpenIds(); |
|
|
|
|
|
|
|
if (null != analyOpenIdList && analyOpenIdList.size() > 0) { |
|
|
|
// 获取access_token
|
|
|
|
String analysis_access_token = WxSendMessageUtils.getAccess_token(analysisAppId, analysisSecret); |
|
|
|
// 拼接URL
|
|
|
|
String analysis_url = url + analysis_access_token; |
|
|
|
Integer analysisResult = sendOpenIdListMessage(analyOpenIdList, analysisTemplate,analysis_url,value); |
|
|
|
log.info("本次小程序消息推送数据端共【" + analyOpenIdList.size() + "】接收者,发送成功【" + analysisResult + "】条。"); |
|
|
|
} |
|
|
|
if(null != workOpenIdList && workOpenIdList.size() > 0){ |
|
|
|
// 获取access_token
|
|
|
|
String work_access_token = WxSendMessageUtils.getAccess_token(workAppId, workSecret); |
|
|
|
// 拼接URL
|
|
|
|
String work_url = url + work_access_token; |
|
|
|
Integer workResult = sendOpenIdListMessage(workOpenIdList,workTemplate,work_url,value); |
|
|
|
log.info("本次小程序消息推送工作端共【" + workOpenIdList.size() + "】接收者,发送成功【" + workResult + "】条。"); |
|
|
|
} |
|
|
|
|
|
|
|
return new Result().ok("消息推送成功!"); |
|
|
|
} |
|
|
|
|
|
|
|
private Integer sendOpenIdListMessage(List<String> openIdList,String templateId,String url,String value){ |
|
|
|
AtomicInteger ai = new AtomicInteger(0); |
|
|
|
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
|
|
|
List<Future<Integer>> list = new ArrayList<>(); |
|
|
|
for(String openId : openIdList){ |
|
|
|
Future<Integer> future = threadPool.submit(new Callable<Integer>() { |
|
|
|
@Override |
|
|
|
public Integer call() throws Exception { |
|
|
|
// 配置模板内容
|
|
|
|
Map<String, TemplateData> m = new HashMap<>(5); |
|
|
|
TemplateData keyword1 = new TemplateData(); |
|
|
|
keyword1.setValue(value); |
|
|
|
m.put("thing1", keyword1); |
|
|
|
TemplateData keyword2 = new TemplateData(); |
|
|
|
String dateStr = sdf.format(new Date()); |
|
|
|
keyword2.setValue(dateStr); |
|
|
|
m.put("time2", keyword2); |
|
|
|
//发送消息
|
|
|
|
String resultMsg = WxSendMessageUtils.sendMessageByOpenId( |
|
|
|
openId, |
|
|
|
url, |
|
|
|
jumpType, |
|
|
|
templateId, |
|
|
|
m, |
|
|
|
lang, |
|
|
|
page); |
|
|
|
System.out.println("接收者【" + openId + "】,发送结果【" + resultMsg + "】"); |
|
|
|
//解析返回信息
|
|
|
|
Map map = JSONObject.parseObject(resultMsg, Map.class); |
|
|
|
if (Integer.parseInt(map.get("errcode").toString()) == 0) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
return 1; |
|
|
|
} |
|
|
|
}); |
|
|
|
list.add(future); |
|
|
|
} |
|
|
|
//循环接收发送结果,相当于一个使线程同步的过程,这个过程是比较耗时的
|
|
|
|
for (int i = 0; i < openIdList.size(); i++) { |
|
|
|
try { |
|
|
|
int resultStatus = list.get(i).get(); |
|
|
|
if (resultStatus == 0) {//发送成功
|
|
|
|
ai.incrementAndGet(); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
e.printStackTrace(); |
|
|
|
} |
|
|
|
} |
|
|
|
return ai.get(); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|