C#微信公众平台开发之高级群发接口

时间:2021-08-28 06:03:13

涉及access_token的获取请参考《c#微信公众平台开发之access_token的获取存储与更新》

一、为了实现高级群发功能,需要解决的问题

1、通过微信接口上传图文消息素材时,json中的图片不是url而是media_id,如何通过微信接口上传图片并获取图片的media_id?

2、图片存储在什么地方,如何获取?

二、实现步骤,以根据openid列表群发图文消息为例

1、准备数据

    我把数据存储在数据库中,imgurl字段是图片在服务器上的相对路径(这里的服务器是自己的服务器,不是微信的哦)。

C#微信公众平台开发之高级群发接口

从数据库中获取数据放到datatable中:

datatable dt = imgitemdal.getimgitemtable(loginuser.orgid, data);

2、通过微信接口上传图片,返回图片的media_id

 取imgurl字段数据,通过mappath方法获取图片在服务器上的物理地址,用filestream类读取图片,并上传给微信

http上传文件代码(httprequestutil类):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/// <summary>
/// http上传文件
/// </summary>
public static string httpuploadfile(string url, string path)
{
 // 设置参数
 httpwebrequest request = webrequest.create(url) as httpwebrequest;
 cookiecontainer cookiecontainer = new cookiecontainer();
 request.cookiecontainer = cookiecontainer;
 request.allowautoredirect = true;
 request.method = "post";
 string boundary = datetime.now.ticks.tostring("x"); // 随机分隔线
 request.contenttype = "multipart/form-data;charset=utf-8;boundary=" + boundary;
 byte[] itemboundarybytes = encoding.utf8.getbytes("\r\n--" + boundary + "\r\n");
 byte[] endboundarybytes = encoding.utf8.getbytes("\r\n--" + boundary + "--\r\n");
 
 int pos = path.lastindexof("\\");
 string filename = path.substring(pos + 1);
 
 //请求头部信息
 stringbuilder sbheader = new stringbuilder(string.format("content-disposition:form-data;name=\"file\";filename=\"{0}\"\r\ncontent-type:application/octet-stream\r\n\r\n", filename));
 byte[] postheaderbytes = encoding.utf8.getbytes(sbheader.tostring());
 
 filestream fs = new filestream(path, filemode.open, fileaccess.read);
 byte[] barr = new byte[fs.length];
 fs.read(barr, 0, barr.length);
 fs.close();
 
 stream poststream = request.getrequeststream();
 poststream.write(itemboundarybytes, 0, itemboundarybytes.length);
 poststream.write(postheaderbytes, 0, postheaderbytes.length);
 poststream.write(barr, 0, barr.length);
 poststream.write(endboundarybytes, 0, endboundarybytes.length);
 poststream.close();
 
 //发送请求并获取相应回应数据
 httpwebresponse response = request.getresponse() as httpwebresponse;
 //直到request.getresponse()程序才开始向目标网页发送post请求
 stream instream = response.getresponsestream();
 streamreader sr = new streamreader(instream, encoding.utf8);
 //返回结果网页(html)代码
 string content = sr.readtoend();
 return content;
}

请求微信接口,上传图片,返回media_id(wxapi类):

?
1
2
3
4
5
6
7
8
9
/// <summary>
/// 上传媒体返回媒体id
/// </summary>
public static string uploadmedia(string access_token, string type, string path)
{
 // 设置参数
 string url = string.format("http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}", access_token, type);
 return httprequestutil.httpuploadfile(url, path);
}
?
1
2
string msg = wxapi.uploadmedia(access_token, "image", path); // 上图片返回媒体id
string media_id = tools.getjsonvalue(msg, "media_id");

传入的path(aspx.cs文件中的代码):

string path = mappath(data);

一个图文消息由若干条图文组成,每条图文有标题、内容、链接、图片等

遍历每条图文数据,分别请求微信接口,上传图片,获取media_id

3、上传图文消息素材

拼接图文消息素材json字符串(imgitemdal类(操作图文消息表的类)):

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/// <summary>
/// 拼接图文消息素材json字符串
/// </summary>
public static string getarticlesjsonstr(pagebase page, string access_token, datatable dt)
{
 stringbuilder sbarticlesjson = new stringbuilder();
 
 sbarticlesjson.append("{\"articles\":[");
 int i = 0;
 foreach (datarow dr in dt.rows)
 {
 string path = page.mappath(dr["imgurl"].tostring());
 if (!file.exists(path))
 {
  return "{\"code\":0,\"msg\":\"要发送的图片不存在\"}";
 }
 string msg = wxapi.uploadmedia(access_token, "image", path); // 上图片返回媒体id
 string media_id = tools.getjsonvalue(msg, "media_id");
 sbarticlesjson.append("{");
 sbarticlesjson.append("\"thumb_media_id\":\"" + media_id + "\",");
 sbarticlesjson.append("\"author\":\"" + dr["author"].tostring() + "\",");
 sbarticlesjson.append("\"title\":\"" + dr["title"].tostring() + "\",");
 sbarticlesjson.append("\"content_source_url\":\"" + dr["texturl"].tostring() + "\",");
 sbarticlesjson.append("\"content\":\"" + dr["content"].tostring() + "\",");
 sbarticlesjson.append("\"digest\":\"" + dr["content"].tostring() + "\",");
 if (i == dt.rows.count - 1)
 {
  sbarticlesjson.append("\"show_cover_pic\":\"1\"}");
 }
 else
 {
  sbarticlesjson.append("\"show_cover_pic\":\"1\"},");
 }
 i++;
 }
 sbarticlesjson.append("]}");
 
 return sbarticlesjson.tostring();
}

上传图文消息素材,获取图文消息的media_id:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/// <summary>
/// 请求url,发送数据
/// </summary>
public static string posturl(string url, string postdata)
{
 byte[] data = encoding.utf8.getbytes(postdata);
 
 // 设置参数
 httpwebrequest request = webrequest.create(url) as httpwebrequest;
 cookiecontainer cookiecontainer = new cookiecontainer();
 request.cookiecontainer = cookiecontainer;
 request.allowautoredirect = true;
 request.method = "post";
 request.contenttype = "application/x-www-form-urlencoded";
 request.contentlength = data.length;
 stream outstream = request.getrequeststream();
 outstream.write(data, 0, data.length);
 outstream.close();
 
 //发送请求并获取相应回应数据
 httpwebresponse response = request.getresponse() as httpwebresponse;
 //直到request.getresponse()程序才开始向目标网页发送post请求
 stream instream = response.getresponsestream();
 streamreader sr = new streamreader(instream, encoding.utf8);
 //返回结果网页(html)代码
 string content = sr.readtoend();
 return content;
}
?
1
2
3
4
5
6
7
/// <summary>
/// 上传图文消息素材返回media_id
/// </summary>
public static string uploadnews(string access_token, string postdata)
{
 return httprequestutil.posturl(string.format("https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token={0}", access_token), postdata);
}
?
1
2
3
string articlesjson = imgitemdal.getarticlesjsonstr(this, access_token, dt);
string newsmsg = wxapi.uploadnews(access_token, articlesjson);
string newsid = tools.getjsonvalue(newsmsg, "media_id");

4、群发图文消息

获取全部关注者openid集合(wxapi类):

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/// <summary>
/// 获取关注者openid集合
/// </summary>
public static list<string> getopenids(string access_token)
{
 list<string> result = new list<string>();
 
 list<string> openidlist = getopenids(access_token, null);
 result.addrange(openidlist);
 
 while (openidlist.count > 0)
 {
 openidlist = getopenids(access_token, openidlist[openidlist.count - 1]);
 result.addrange(openidlist);
 }
 
 return result;
}
 
/// <summary>
/// 获取关注者openid集合
/// </summary>
public static list<string> getopenids(string access_token, string next_openid)
{
 // 设置参数
 string url = string.format("https://api.weixin.qq.com/cgi-bin/user/get?access_token={0}&next_openid={1}", access_token, string.isnullorwhitespace(next_openid) ? "" : next_openid);
 string returnstr = httprequestutil.requesturl(url);
 int count = int.parse(tools.getjsonvalue(returnstr, "count"));
 if (count > 0)
 {
 string startflg = "\"openid\":[";
 int start = returnstr.indexof(startflg) + startflg.length;
 int end = returnstr.indexof("]", start);
 string openids = returnstr.substring(start, end - start).replace("\"", "");
 return openids.split(',').tolist<string>();
 }
 else
 {
 return new list<string>();
 }
}

list<string> openidlist = wxapi.getopenids(access_token); //获取关注者openid列表
拼接图文消息json(wxmsgutil类):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
/// 图文消息json
/// </summary>
public static string createnewsjson(string media_id, list<string> openidlist)
{
 stringbuilder sb = new stringbuilder();
 sb.append("{\"touser\":[");
 sb.append(string.join(",", openidlist.convertall<string>(a => "\"" + a + "\"").toarray()));
 sb.append("],");
 sb.append("\"msgtype\":\"mpnews\",");
 sb.append("\"mpnews\":{\"media_id\":\"" + media_id + "\"}");
 sb.append("}");
 return sb.tostring();
}

群发代码:

?
1
2
3
4
5
6
7
8
9
10
resultmsg = wxapi.send(access_token, wxmsgutil.createnewsjson(newsid, openidlist));
 
 
/// <summary>
/// 根据openid列表群发
/// </summary>
public static string send(string access_token, string postdata)
{
 return httprequestutil.posturl(string.format("https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token={0}", access_token), postdata);
}

供群发按钮调用的方法(data是传到页面的id,根据它从数据库中取数据):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/// <summary>
/// 群发
/// </summary>
public string send()
{
 string type = request["type"];
 string data = request["data"];
 
 string access_token = adminutil.getaccesstoken(this); //获取access_token
 list<string> openidlist = wxapi.getopenids(access_token); //获取关注者openid列表
 userinfo loginuser = adminutil.getloginuser(this); //当前登录用户
 
 string resultmsg = null;
 
 //发送文本
 if (type == "1")
 {
 resultmsg = wxapi.send(access_token, wxmsgutil.createtextjson(data, openidlist));
 }
 
 //发送图片
 if (type == "2")
 {
 string path = mappath(data);
 if (!file.exists(path))
 {
  return "{\"code\":0,\"msg\":\"要发送的图片不存在\"}";
 }
 string msg = wxapi.uploadmedia(access_token, "image", path);
 string media_id = tools.getjsonvalue(msg, "media_id");
 resultmsg = wxapi.send(access_token, wxmsgutil.createimagejson(media_id, openidlist));
 }
 
 //发送图文消息
 if (type == "3")
 {
 datatable dt = imgitemdal.getimgitemtable(loginuser.orgid, data);
 string articlesjson = imgitemdal.getarticlesjsonstr(this, access_token, dt);
 string newsmsg = wxapi.uploadnews(access_token, articlesjson);
 string newsid = tools.getjsonvalue(newsmsg, "media_id");
 resultmsg = wxapi.send(access_token, wxmsgutil.createnewsjson(newsid, openidlist));
 }
 
 //结果处理
 if (!string.isnullorwhitespace(resultmsg))
 {
 string errcode = tools.getjsonvalue(resultmsg, "errcode");
 string errmsg = tools.getjsonvalue(resultmsg, "errmsg");
 if (errcode == "0")
 {
  return "{\"code\":1,\"msg\":\"\"}";
 }
 else
 {
  return "{\"code\":0,\"msg\":\"errcode:"
  + errcode + ", errmsg:"
  + errmsg + "\"}";
 }
 }
 else
 {
 return "{\"code\":0,\"msg\":\"type参数错误\"}";
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助。