${year} 年 ${month} 月 ${day} 日
此功能分两部分,第一部分定时器每天定点推送一条URL+图片+文字,第二部分点击URL进入页面,能看到生日祝福文字、背景图片、音乐。
ApplicationContext-elasticJob.xml设置定时任务,指定触发频率和运行类,
/wxapp/src/main/resources/spring/ApplicationContext-elasticJob.xml设置定时任务:
定时器知识:https://blog.csdn.net/Linweiqiang5/article/details/86741258
/wx-quartz-job/src/main/java/com/aoyang/wxapp/quartz/job/BirthdayBlessingDailyJob.java
定时推送类BirthdayBlessingDailyJob,注入两个Service
staffService,用于查询今天过生日的人员名单,
sendService,用于将信息推送给人员名单,
/**
* Project Name: 澳洋信息系统微信台平台 Date:2019年8月20日 Copyright(c) 2019 All Rights Reserved
*
* @author qiudc.
*
*/
package com.aoyang.wxapp.quartz.job;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
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.Component;
import com.aoyang.weixin.corp.model.msg.Article;
import com.aoyang.weixin.corp.model.msg.News;
import com.aoyang.weixin.corp.model.msg.resp.WxCorpNewsResponseMessage;
import com.aoyang.weixin.corp.service.WxCorpMessageSendService;
import com.aoyang.weixin.util.OAuth2Utils;
import com.aoyang.wxapp.service.fhoa.staff.StaffManager;
import com.aoyang.wxapp.util.PageData;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
@Component("birthdayBlessingDailyJob")
public class BirthdayBlessingDailyJob implements SimpleJob {
private static final Logger LOGGER = LoggerFactory.getLogger(BirthdayBlessingDailyJob.class);
private static final String BIRTHDAY_BLESSING_URL = "weixin/hr/birthdayBlessing";
@Resource(name="staffService")
private StaffManager staffService;
@Autowired
private WxCorpMessageSendService sendService;
@Value("${Hostname}")
private String hostName;
@Value("${agent.hr}")
private int hrAgentId;
public void syncVehicleReportDaily() throws Exception {
LOGGER.info("生日祝福日报推送开始......");
try {
PageData resultPd = staffService.getBirthdayStaffList();
if (resultPd != null) {
String birtydayStaffId = resultPd.getString("STAFF_ID_LIST");
String birtydayStaffIdAll = birtydayStaffId.replace(",", "|");
//推送的文字内容、图片url、跳转链接
String sendContent = String.format("澳洋集团祝您生日快乐!");
String picurl = "http://weixin.aoyang.com/group1/M00/05/8D/wKgBxl1LeCCADe4-AAoVjP4jB4A736.jpg";
String url = OAuth2Utils.getOAuthUrl(hostName,BIRTHDAY_BLESSING_URL,hrAgentId);
List articles = new ArrayList();
articles.add(new Article("生日祝福", sendContent, picurl, url));
News news = new News();
news.setArticles(articles);
//推送微信通知给所有今天过生日的人
WxCorpNewsResponseMessage message = new WxCorpNewsResponseMessage();
message.setNews(news);
message.setTouser(birtydayStaffIdAll);
//隶属于IT新服务
message.setAgentid(hrAgentId);
message.setTotag("@all"); //@all表示忽略本参数
message.setToparty("@all");
String backMsg = sendService.sendMessage(message);
backMsg = (backMsg == null ? "" : backMsg);
LOGGER.info("[ITSM] 推送消息 : 生日祝福" + ";返回的数据为:" + backMsg);
}
} catch (Exception e) {
LOGGER.error("生日祝福日报推送时发生异常,{}", e);
}
LOGGER.info("生日祝福日报推送定时任务执行完毕");
}
@Override
public void execute(ShardingContext shardingContext) {
try {
LOGGER.info("分片值:" + shardingContext.getShardingItem());
syncVehicleReportDaily();
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
}
}
/wx-system-api/src/main/java/com/aoyang/wxapp/service/fhoa/staff/StaffManager.java
StaffManager接口
/**
* Project Name: 澳洋信息系统微信管理平台
* Date:2016年10月10日
* Copyright(c) 2016 All Rights Reserved
*/
package com.aoyang.wxapp.service.fhoa.staff;
import java.util.List;
import java.util.Map;
import com.aoyang.wxapp.entity.Page;
import com.aoyang.wxapp.util.PageData;
/**
* 员工管理接口
*/
public interface StaffManager{
/**通过id获取数据
* @param pd
* @throws Exception
*/
public PageData findById(PageData pd)throws Exception;
/**
* 根据用户ID查找.
*
* @param userId 用户ID.
* @return
* @throws Exception
*/
public PageData findByUserId(String userId) throws Exception;
/**
* 获取当天年月日String.
*@return String
*/
String getTodayDate()throws Exception;
/**
* 生日祝福人员列表.
*@return List
* @param
*/
public PageData getBirthdayStaffList()throws Exception;
}
/wx-system-service/src/main/java/com/aoyang/wxapp/service/fhoa/staff/impl/StaffService.java
StaffService实现StaffManager接口,
/**
* Project Name: 澳洋信息系统微信管理平台
* Date:2016年10月10日
* Copyright(c) 2016 All Rights Reserved
*/
package com.aoyang.wxapp.service.fhoa.staff.impl;
import com.aoyang.wxapp.dao.DaoSupport;
import com.aoyang.wxapp.entity.Page;
import com.aoyang.wxapp.service.fhoa.staff.StaffManager;
import com.aoyang.wxapp.util.PageData;
/**
* 员工管理.
*/
@Service("staffService")
public class StaffService implements StaffManager{
@Resource(name = "daoSupport")
private DaoSupport dao;
/**通过id获取数据
* @param pd
* @throws Exception
*/
public PageData findById(PageData pd)throws Exception{
return (PageData)dao.findForObject("StaffMapper.findById", pd);
}
@Override
public PageData findByUserId(String userId) throws Exception {
PageData pd = new PageData();
pd.put("STAFF_ID", userId);
Object obj = dao.findForObject("StaffMapper.findByUserId", userId);
if(obj != null) {
pd = (PageData)obj;
return pd;
}
return null;
}
/**
* 获取当天年月日String.
*@return String
*/
@Override
public String getTodayDate() throws Exception {
return (String)dao.findForObject("StaffMapper.getTodayDate", null);
}
/**
* 生日祝福人员列表.
*@return List
* @param
*/
@Override
public PageData getBirthdayStaffList() throws Exception {
return (PageData) dao.findForObject("StaffMapper.getBirthdayStaffList",null);
}
}
/wxapp/src/main/resources/mybatis1/fhoa/StaffMapper.xml
xml文件从数据库读取数据
OA_STAFF
NAME,
NAME_EN,
BIANMA,
DEPARTMENT_ID,
FUNCTIONS,
TEL,
EMAIL,
SEX,
BIRTHDAY,
NATION,
JOBTYPE,
JOBJOINTIME,
FADDRESS,
POLITICAL,
PJOINTIME,
SFID,
MARITAL,
DJOINTIME,
POST,
POJOINTIME,
EDUCATION,
SCHOOL,
MAJOR,
FTITLE,
CERTIFICATE,
CONTRACTLENGTH,
CSTARTTIME,
CENDTIME,
ADDRESS,
USER_ID,
BZ,
HIDETEL,
UPDATE_DATE,
QQ,
WECHAT,
STATION,
POSITION,
HIREDATE,
SHORTPHONE,
WORKPLACE,
WORKPHONE,
STAFF_ID
/wx-weixin-core/src/main/java/com/aoyang/weixin/util/OAuth2Utils.java
package com.aoyang.weixin.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 微信OAuth工具类.
*
* @author [email protected].
*
*/
public class OAuth2Utils {
private static Log logger = LogFactory.getLog(OAuth2Utils.class);
private OAuth2Utils() {};
/** 回调验证的URL前缀. */
private static final String OAUTH_URL_PREFIX = "http://weixin.aoyang.com/wxapp/weixin/authenticate.do?state=";
private static final String OAUTH_URL_PREFIX_WITHOUT_DOMAIN = "/wxapp/weixin/authenticate.do?agentId=AGENT_ID&state=STATE";
private static final String HTTP_PREFIX = "http://";
/**
*
* @param hostName
* : 域名
* @param contextPath
* @param agentId
* @return
*/
public static String getOAuthUrl(String hostName, String contextPath, int agentId) {
if (contextPath == null || contextPath.trim().length() == 0) {
throw new IllegalArgumentException("contextPath 不能为null");
}
// 解决contextPath携带参数的问题
hostName = hostName.startsWith(HTTP_PREFIX) ? hostName : HTTP_PREFIX + hostName;
String url = hostName + OAUTH_URL_PREFIX_WITHOUT_DOMAIN;
String newUrl = url.replace("AGENT_ID", String.valueOf(agentId)).replace("STATE", contextPath);
logger.info("拼接替换后的url为:" + newUrl);
return newUrl;
}
/**
* 获取回调的URL地址,此地址可以获取企业微信用户身份(UserId).
*
* @param contextPath
* 应用程序上下文路径,不能为null
或空值.
* 如:weixin/addresslist/showmygroup.do, 不包含协议、端口号、域名、程序路径等.
* @return 指向我们程序且回以获取用户身份信息的URL.
*/
@Deprecated
public static String getOAuthUrl(String contextPath, int agentId) {
if (contextPath == null || contextPath.trim().length() == 0) {
throw new IllegalArgumentException("contextPath 不能为null");
}
String url = OAUTH_URL_PREFIX + contextPath;
url = url + "&agentId=" + agentId;
logger.info("生成URL -->" + url);
return url;
}
}
/wx-weixin-api/src/main/java/com/aoyang/weixin/corp/service/WxCorpMessageSendService.java
/**
* Project Name: 澳洋信息系统微信台平台
* Date:2016年11月12日
* Copyright(c) 2016 All Rights Reserved
* @author [email protected].
*
*/
package com.aoyang.weixin.corp.service;
import com.aoyang.weixin.corp.model.msg.resp.WxCorpResponseMessage;
import com.aoyang.weixin.exception.WxException;
/**
* 企业微信号向微信用户发送消息服务.
*
* @author [email protected]
*
*/
public interface WxCorpMessageSendService {
/**
* 企业接口向下属关注用户发送微信消息.
*
* @param message
* 要发送的消息.
* @return JSON格式的返回结果.格式如下:
*
*
* {
* "errcode": 0,
* "errmsg": "ok",
* "invaliduser": "UserID1",
* "invalidparty":"PartyID1",
* "invalidtag":"TagID1"
* }
*
* @return JSON格式的返回结果,可能 会返回 null
.
*
*
* @throws WxException 如果无法发送抛出异常。
*/
public String sendMessage(WxCorpResponseMessage message) throws WxException;
/**
* 企业接口向下属关注用户发送微信消息.
*
* @param jsonWxMessage String格式的微信消息.
* @return JSON格式的返回结果,可能 会返回 null
.
* @throws WxException 如果无法发送抛出异常.
*/
public String sendMessage(String jsonWxMessage) throws WxException;
/**
* 企业接口向下属关注用户发送微信文本消息.
*
* @param touser
* 成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,
* 则向关注该企业应用的全部成员发送
* @param toparty
* 部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
* @param totag
* 标签ID列表,多个接收者用‘|’分隔。当touser为@all时忽略本参数
* @param content
* 消息内容
* @param agentId
* 企业微信应用ID,可以在微信管理后台获取不同的应用ID.
* @return
*/
public String sendTextMessage(String touser, String toparty, String totag,
String content, Integer agentId) throws WxException;
}
/wx-weixin-core/src/main/java/com/aoyang/weixin/corp/model/msg/Article.java
package com.aoyang.weixin.corp.model.msg;
/**
* 图文类.
*
* @author [email protected]
*
*/
public class Article {
/**图文标题.*/
private String title;
/**图文描述.*/
private String description;
/**图片链接,支持JPG,PNG,较好的效果为大图640*320,小图80*80.*/
private String picurl;
/**点击图文消息跳转链接.*/
private String url;
/**
* 构造函数.
*/
public Article() {
}
/**
* 构造函数.
*
* @param title 图文标题.
* @param description 图文描述.
* @param picUrl 图片链接.
* @param url 跳转链接.
*/
public Article(String title, String description, String picUrl, String url) {
super();
this.title = title;
this.description = description;
this.picurl = picUrl;
this.url = url;
}
/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return the picUrl
*/
public String getPicurl() {
return picurl;
}
/**
* @param picurl the picUrl to set
*/
public void setPicurl(String picurl) {
this.picurl = picurl;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
}
/wx-weixin-core/src/main/java/com/aoyang/weixin/corp/model/msg/News.java
/**
* Project Name: 澳洋信息系统微信台平台
* Date:2016年10月9日
* Copyright(c) 2016 All Rights Reserved
* @author [email protected].
*
*/
package com.aoyang.weixin.corp.model.msg;
import java.util.Arrays;
import java.util.List;
public class News {
private List articles;
public News() {
}
public News(List article) {
this.articles = article;
}
public News(Article...articles ) {
this.articles = Arrays.asList(articles);
}
public List getArticles() {
return articles;
}
public void setArticles(List article) {
this.articles = article;
}
}
配置文件:
/wxapp/src/main/resources/env/dev.properties
db_url=jdbc:oracle:thin:@172.30.112.197:1521:orclutf8
db_driverClassName=oracle.jdbc.OracleDriver
db_username=itsm20
db_password=Itsm20.123
#huashengke---xinkefuwu
wx_corpID=ww22141d223bc1a1ad
wx_token=lFTdRHxw2CZsNnPY1rm
wx_encodingAESKey=o0JcSyWPz3HW5sbhpAbSjMUTWJtfC97kOf8hgQybkDc
wx_secret=v6DBWgCBbh6SiWoznl1AfAf-ZAta-xEftXy2JfqMGl0
wx_hostname=263fw85879.qicp.vip:19303
#wx_hostname=2399016x6l.qicp.vip:51286
wx_agent_hr=1000016
/wxapp/src/main/resources/weixin.properties 调取 dev.properties
CorpID=${wx_corpID}
Token=${wx_token}
EncodingAESKey=${wx_encodingAESKey}
Secret=${wx_secret}
Hostname=${wx_hostname}
agent.inventory=${wx_agent_inventory}
agent.itsm.new=${wx_agent_itsm_new}
agent.itsm.new.workbench=${wx_agent_itsm_new_workbench}
agent.stats=${wx_agent_stats}
agent.hr=${wx_agent_hr}
consumables.apply.templateId=${consumables_apply_templateId}
knowledge.audit.templateId=${knowledge_audit_templateId}
out.sourcing.templateId=${out_sourcing_templateId}
consumables.outbound.templateId=${consumables_outbound_templateId}
nonfixed.asset.nonvalueChange.templateId=${nonfixed_asset_nonvalueChange_templateId}
asset.inventory.audit.templateId=${asset_inventory_audit_templateId}
fixed.asset.nonvalueChange.templateId=${fixed_asset_nonvalueChange_templateId}
测试时使用的是:/wxapp/src/test/resources/weixin.properties
#huashengke---xinkefuwu
CorpID=ww22141d223bc1a1ad
Token=lFTdRHxw2CZsNnPY1rm
EncodingAESKey=o0JcSyWPz3HW5sbhpAbSjMUTWJtfC97kOf8hgQybkDc
Secret=v6DBWgCBbh6SiWoznl1AfAf-ZAta-xEftXy2JfqMGl0
#Hostname=2m04471c37.51mypc.cn:14127
Hostname=263fw85879.qicp.vip:19303
#Hostname=wei.aoyang.com
agent.hr=1000016
/wxapp/src/main/java/com/aoyang/wxapp/controller/hr/HrController.java
/**
* Project Name: 澳洋信息系统微信台平台
* Date:2017年1月3日
* Copyright(c) 2016 All Rights Reserved
* @author gongkx
*
*/
package com.aoyang.wxapp.controller.hr;
import java.util.Calendar;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.aoyang.wxapp.controller.BaseController;
import com.aoyang.wxapp.service.fhoa.staff.StaffManager;
import com.aoyang.wxapp.service.kq.KqService;
import com.aoyang.wxapp.service.salary.HrService;
import com.aoyang.wxapp.util.DateTimeUtils;
import com.aoyang.wxapp.util.PageData;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
@Controller
@RequestMapping(value = "/weixin/hr")
public class HrController extends BaseController {
private static final Logger LOGGER = LoggerFactory.getLogger(HrController.class);
@Autowired
private HrService hrService;
@Resource(name = "staffService")
private StaffManager staffService;
@Autowired
KqService kq;
/**
* 生日祝福推送.
* qiudc
* @param page
* @throws Exception
*/
@RequestMapping(value = "/birthdayBlessing")
public ModelAndView birthdayBlessing(ModelAndView model) throws Exception {
model.setViewName("hr/birthdayBlessing");
String userId = getCurrentUserId();
userId = "AY006278";
if (!StringUtils.isEmpty(userId)) {
PageData staff = staffService.findByUserId(userId);
String todayDate = staffService.getTodayDate();
String year = todayDate.substring(0, 4); //2019-08-25
String birthday = staff.getString("BIRTHDAY");
String month = birthday.substring(5, 7);
String day = birthday.substring(8, 10);
model.addObject("year", year);
model.addObject("month", month);
model.addObject("day", day);
model.addObject("staff", staff);
return model;
}
return model;
}
}
页面JSP:
/wxapp/src/main/webapp/WEB-INF/jsp/hr/birthdayBlessing.jsp
注意导入音乐的写法,判断性别的写法,
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
祝您生日快乐
css渲染文件:
/wxapp/src/main/webapp/static/ace/css/birthdayblessing.css
将 FZSEJW.ttf 字体文件放入 /wxapp/src/main/webapp/static/ace/fonts/FZSEJW.ttf
注意引用字体的写法 @font-face font-family ,
和 字体阴影的写法 text-shadow:2.5px 2.5px 2.5px #ffffff;
/* 方正少儿体fonts for /wxapp/src/main/webapp/WEB-INF/jsp/hr/birthdayBlessing.jsp */
@font-face{
font-family: 'fangzhengshaoer';
src: url('../fonts/FZSEJW.ttf');
}
html {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
font-family: fangzhengshaoer;
font-size: 18px;
color: #32282e;
text-shadow:2.5px 2.5px 2.5px #ffffff;
}
summary {
display: block;
}
video {
display: inline-block;
vertical-align: baseline;
}
audio:not([controls]) {
display: none;
height: 0;
}
写测试类,推送生日祝福给用户:
/wxapp/src/test/java/com/aoyang/wxapp/quartz/job/BirthdayBlessingDailyJobTest.java
运行测试方法,推送生日祝福到微信,点击推送消息,看能否打开网页。
/**
* All rights Reserved,Designed By www.aoyang.com
* @Title EmployeeSyncFromHRJobTest.java
* @Package com.aoyang.wxapp.quartz.job
* @Description :
* @Author daixiongyan
* @date 2019年8月8日
* @Version V1.0
* @Copyright : 2019.www.aoyang.com
*/
package com.aoyang.wxapp.quartz.job;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.aoyang.wxapp.BaseJunit4;
import com.aoyang.wxapp.service.fhoa.staff.StaffManager;
import com.aoyang.wxapp.util.PageData;
/**
* @ClassName: EmployeeSyncFromHRJobTest
* @Description: TODO(这里用一句话描述这个类的作用)
* @author qiudechao
* @date 2019年8月8日
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
public class BirthdayBlessingDailyJobTest extends BaseJunit4{
@Resource(name="birthdayBlessingDailyJob")
private BirthdayBlessingDailyJob birthdayBlessingDailyJob;
@Resource(name="staffService")
private StaffManager staffService;
private static final Logger LOGGER = LoggerFactory.getLogger(BirthdayBlessingDailyJobTest.class);
//birthdayBlessingDailyJob.syncVehicleReportDaily();分成两部分测试
@Test
public void test() {
try {
birthdayBlessingDailyJob.syncVehicleReportDaily();
} catch (Exception e) {
LOGGER.error("生日祝福出现异常:{}", e);
}
}
}
电脑端浏览生日祝福页面效果:
本地网址:http://localhost:9090/wxapp/weixin/hr/birthdayBlessing.do
外网映射网址:http://2399016x6l.qicp.vip:51286/wxapp/weixin/hr/birthdayBlessing.do
相关连接:
利用花生壳搭建微信小应用 https://blog.csdn.net/qiudechao1/article/details/100141669