一、為了實現高級群發功能,需要解決的問題
1、通過微信接口上傳圖文消息素材時,JSon中的圖片不是url而是media_id,如何通過微信接口上傳圖片並獲取圖片的media_id?
2、圖片存儲在什麼地方,如何獲取?
二、實現步驟,以根據OpenID列表群發圖文消息為例
1、准備數據
我把數據存儲在數據庫中,ImgUrl字段是圖片在服務器上的相對路徑(這裡的服務器是自己的服務器,不是微信的哦)。
從數據庫中獲取數據放到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類):
/// <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 10resultMsg = 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參數錯誤\"}"
;
}
}