一、前言
在上一篇博客中,小编简单向大家介绍了微信的各个模块。相信大家也会宏观的了解了一点,不过要想真正的熟悉微信,还是应该动手敲一些项目,下面小编就向大家介绍一下微信公众平台中的——微信消息推送。
二、项目说明
小编的这个项目需求是与考试相关的。项目需求学生可以在考试之前或者考试之后查询自己的考场情况。然后在考试之前的前一天会在微信定时推送消息到用户。
俗话说,一张图胜过前言万语:
这里小编就重点给大家分享一下,如何使用微信发送定时消息。
三、代码实战
3.1 技术选型
小编的项目使用了Quartz+微信群发消息+.Net三层架构+MySQL数据库这些技术点。
3.2 项目宏观图
3.3 定时系统搭建
下载定时系统demo:https://www.quartz-scheduler.net/download.html
Quartz.Net.Job项目中,包含了两个文件,一个是quartz_jobs.xml文件,这个文件主要配置定时任务job和触发器,另个是任务具体执行的方法DemoJob1:
quartz_jobs.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file contains job definitions in schema version 2.0 format -->
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
<processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives>
<schedule>
<!--定时查询是否有考试信息 Job-->
<job>
<name>DemoJob1</name>
<group>DeomJobGroup</group>
<description>Quartz.Net任务</description>
<job-type>Quartz.Net.Job.DemoJob1,Quartz.Net.Job</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<!--定时查询是否有考试信息 触发器 每30秒执行一次DemoJob1任务-->
<trigger>
<cron>
<name>DemoJob1Trigger</name>
<group>DeomJobTriggerGroup</group>
<job-name>DemoJob1</job-name>
<job-group>DeomJobGroup</job-group>
<cron-expression>0 25 21 * * ?</cron-expression>
</cron>
</trigger>
</schedule>
</job-scheduling-data>
Quartz.Net.Service项目中,包含了App.config、program.cs、PushWechatService.cs、quartz.config
3.4 Windows服务调用Quartz.net 实现消息调度
借鉴http://blog.csdn.net/lenovouser/article/details/46048199
3.4 定时器执行向微信群发消息
微信群发消息接口介绍:
在微信的官方文档中,发送消息-群发接口和原创校验,规定“在公众平台网站上,为订阅号提供了每天一条的群发权限,为服务号提供每月(自然月)4条的群发权限。而对于某些具备开发能力的公众号运营者,可以通过高级群发接口,实现更灵活的群发能力。”
执行的定时发送推送消息任务:
#region 执行的定时发送推送消息任务-王雷-2017年7月17日21:32:58
/// <summary>
/// 执行的定时发送推送消息任务-王雷-2017年7月17日21:32:58
/// </summary>
/// <param name="context"></param>
public void Execute(IJobExecutionContext context)
{
_logger.InfoFormat("推送电子准考证成功执行" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
//1.获取服务器时间
string date = publicbll.GetDate();
//2.获取所有明天有考试的学生的考试信息
date = Convert.ToDateTime(date).AddDays(1).ToString("yyyy-MM-dd");
List<StudentWechatViewModel> list = pullwechatBll.QueryStudentWechatInfoByDate(date);
string access_token = getAccessToken();
string url = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=" + access_token;
//3.依次遍历执行
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i] != null)
{
SendWechat(list, i,url);
}
}
}
}
#endregion
获取accesstoken:
#region 获取accesstoken-李鑫超-2017年7月19日10:52:41
/// <summary>
/// 获取accesstoken-李鑫超-2017年7月19日10:52:41
/// </summary>
/// <returns></returns>
public static string getAccessToken()
{
string appid = System.Configuration.ConfigurationManager.AppSettings["appid"];
string appsecret = System.Configuration.ConfigurationManager.AppSettings["appsecret"];
string access_token = null;
string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
string jsonReturn = "";
HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(url);
httprequest.Method = "GET";
HttpWebResponse response = (HttpWebResponse)httprequest.GetResponse();
using (Stream steam = response.GetResponseStream())
{
StreamReader reader = new StreamReader(steam, Encoding.GetEncoding("gb2312"));
jsonReturn = reader.ReadToEnd();
steam.Close();
}
JObject jo = JObject.Parse(jsonReturn);
access_token = jo["access_token"].ToString();
return access_token;
}
#endregion
向微信发送指定推送消息:
#region 向微信发送指定推送消息-李鑫超-2017年7月17日21:31:52
/// <summary>
/// 向微信发送指定推送消息-李鑫超-2017年7月17日21:31:52
/// </summary>
/// <param name="list">考试消息泛型</param>
/// <param name="i"></param>
private static void SendWechat(List<StudentWechatViewModel> list, int i, string url)
{
//string postText = "{\"touser\":[\"ozxdo1oRTknxNiem6MDdRh0_4nR8\",\"ozxdo1p4TEfA2xVXE-IGj8Mt0b-0\"],\"msgtype\": \"text\",\"text\": { \"content\": \"您明天有考试呦~\\n请提前准备纸笔和学生证\\n\\n\\n考试信息详情可点击下方\n【查询考试】" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "\"}}";
string postText = "{\"touser\":[\"" + list[i].WeChatId + "\",\"\"],\"msgtype\": \"text\",\"text\": { \"content\": \"【 考试提醒 】\\n\\n\\n" + list[i].StudentName + "同学,你好!\\n明天有考试,请做好准备\\n\\n考试科目:" + list[i].ExamName + "\\n考试日期:" + list[i].Date + "\\n考试时间:" + list[i].StartTime + " - " + list[i].EndTime + "\\n考试地点:" + list[i].ExamPlace + "-" + list[i].SeatNo + "号\\n\\n" + "请提前准备好文具和证件\\n详细情况可点击“查考场”进行查询\\n\\n" + "祝您考试顺利~~\\n\\n\\n" + "-------------------------------\\n" + "大米时代 · 技术支持\\n" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "\\n\\n▄▆█ 雷哥搞事情 █▆▄\"}}";
Encoding encoding = Encoding.GetEncoding("utf-8");
byte[] bytesToPost = encoding.GetBytes(postText);
string res = Post(url, bytesToPost);
Console.WriteLine(res);
}
#endregion
通过post方式把数据推送:
#region 通过post方式把数据推送-李鑫超-2017年7月17日17:22:21
/// <summary>
/// 通过post方式把数据推送-李鑫超-2017年7月17日17:22:21
/// </summary>
/// <param name="url"></param>
/// <param name="bytesToPost"></param>
/// <returns></returns>
private static string Post(string url, byte[] bytesToPost)
{
if (String.IsNullOrEmpty(url))
return "url参数为空值";
if (bytesToPost == null)
return "post数据为空值";
string ResponseString = "";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
System.Net.ServicePointManager.DefaultConnectionLimit = 50;
request.KeepAlive = false;
request.Method = "POST";
request.ContentType = "text/xml";//提交xml
request.ContentLength = bytesToPost.Length;
Stream writer = request.GetRequestStream();
writer.Write(bytesToPost, 0, bytesToPost.Length);
HttpWebResponse HttpWebRespon = (HttpWebResponse)request.GetResponse();
StreamReader myStreamReader = new StreamReader(HttpWebRespon.GetResponseStream(), Encoding.UTF8);
ResponseString = myStreamReader.ReadToEnd();
myStreamReader.Close();
writer.Flush();
if (writer != null)
{
writer.Close();
}
if (request != null)
{
request.Abort();
}
return ResponseString;
}
#endregion
小编效果:
四、小结
代码如人生,自己的代码还是得自己写。
如果不深刻的理解自己的代码就会感到很蒙。多多总结,就会有收获。