上一篇已经能够成功监听微信的消息了,现在只剩最后一个功能发送消息了.
发消息我只做了两个功能:发送文字和发送图片,其他的不太用的到,就没有做.
首先是发送普通文字消息
发送文字很简单,如图只有一个接口webwxsendmsg BaseRequest和之前的监听消息是一样的,另外一个Msg Type:1就是文本消息(Type就是监听消息的时候返回的Type类型)ClientMsgId和LocalID在源码中都是当前时间戳+4位随机数字,FromUserName当然是填自己的UserName了(监听里初始化的时候的自己的UserName),ToUserName当然是填发送方了. Content就是具体要发送的内容了.
如果发送中文出来乱码的话注意发送的data编码得是utf-8
当返回的消息BaseResponse.Ret == 0
的时候,就表示你发送成功了.
接下来是发送图片消息
发送图片通过抓包可以发现是两个接口
1.上传文件 webwxuploadmedia?f=json
其他的根据抓到的包来填值都没问题
主要有一个参数是uploadmediarequest要观察一下源码来填内容.
参数比较多不一一说明,其中FileMd5其实没关系,不用管随便传个值都可以,我是对图片名称+图片大小进行md5加密后传送过去的.
上传图片需要用multipart/form-data
形式发送,这里附上我自己封装的上传方法供大家参考
//上传图片消息
private HttpResult WebWXUpLoadPicture(Contact model, string filePath)
{
string boundary = "----WebKitFormBoundary" + DateTime.Now.Ticks.ToString("x");
var fileInfo = new FileInfo(filePath);
List<FormItemModel> data = new List<FormItemModel>();
//id
data.Add(new FormItemModel("id", "WU_FILE_" + _fileId++));
//name
data.Add(new FormItemModel("name", fileInfo.Name));
//type
data.Add(new FormItemModel("type", System.Web.MimeMapping.GetMimeMapping(filePath)));
//lastModifiedDate
data.Add(new FormItemModel("lastModifiedDate", fileInfo.LastWriteTime.ToString("yyyy-MM-dd tt hh:mm:ss")));
//size
data.Add(new FormItemModel("size", fileInfo.Length.ToString()));
//mediatype
data.Add(new FormItemModel("mediatype", "pic"));
//uploadmediarequest
string md5 = Utils.EncryptToMD5(fileInfo.Name + fileInfo.Length);
PicModel pic = new PicModel()
{
UploadType = 2,
BaseRequest = new BaseRequest(this._wxModel),
TotalLen = fileInfo.Length,
FromUserName = this.User.UserName,
ToUserName = model.UserName,
FileMd5 = md5
};
data.Add(new FormItemModel("uploadmediarequest", JsonHelper.SerializeObject(pic)));
//webwx_data_ticket
string ticket = this.GetCookie("webwx_data_ticket");
data.Add(new FormItemModel("webwx_data_ticket", ticket));
//pass_ticket
data.Add(new FormItemModel("pass_ticket", this._wxModel.pass_ticket));
//file
data.Add(new FormItemModel("filename", fileInfo.Name, filePath));
var bytes = CreateFileByte(data, boundary);
HttpItem item = new HttpItem()
{
URL = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json",
Method = "POST",
PostDataType = PostDataType.Byte,
ContentType = "multipart/form-data; boundary=" + boundary,
PostEncoding = Encoding.UTF8,
PostdataByte = bytes
};
HttpHelper http = new HttpHelper();
var rst = http.GetHtml(item);
return rst;
}
//实体类模型
public class FormItemModel
{
public FormItemModel(string key, string value)
{
this.Key = key;
this.Value = value;
}
public FormItemModel(string key, string name, string path)
{
this.Key = key;
this.Value = name;
this.FilePath = path;
}
/// <summary>
/// 表单键,request["key"]
/// </summary>
public string Key { set; get; }
/// <summary>
/// 表单值,上传文件时为文件名
/// </summary>
public string Value { set; get; }
/// <summary>
/// 是否是文件
/// </summary>
public bool IsFile
{
get
{
if (string.IsNullOrEmpty(FilePath) && FileContent == null) return false;
return true;
}
}
public byte[] GetFileBytes(Encoding encoding)
{
if (encoding == null) encoding = Encoding.UTF8;
if (IsFile)
{
try
{
if (!string.IsNullOrEmpty(FilePath))
{
using (FileStream fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, bytes.Length);
return bytes;
}
}
else
{
byte[] bytes = new byte[FileContent.Length];
FileContent.Read(bytes, 0, bytes.Length);
FileContent.Seek(0, SeekOrigin.Begin);
return bytes;
}
}
catch (Exception)
{
return null;
}
}
else
{
return null;
}
}
//如果是文件,下面两个只要填一个即可.
/// <summary>
/// 上传的文件路径
/// </summary>
public string FilePath { set; get; }
/// <summary>
/// 文件流
/// </summary>
public Stream FileContent { get; set; }
}
//核心postdata 字节创建方法
private byte[] CreateFileByte(List<FormItemModel> formItems, string boundary, Encoding encoding = null)
{
if (encoding == null) encoding = Encoding.UTF8;
Stream postStream = new MemoryStream();
//文件模板
string fileFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" +
"\r\nContent-Type: application/octet-stream" +
"\r\n\r\n";
//文本数据模板
string dataFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}";
foreach (var item in formItems)
{
string formdata = null;
if (item.IsFile)
{ //文件
formdata = string.Format(
fileFormdataTemplate,
item.Key, //表单键
item.Value);
}
else
{ //文本
formdata = string.Format(
dataFormdataTemplate,
item.Key,
item.Value);
}
byte[] formdataBytes = null;
if (postStream.Length == 0)
formdataBytes = encoding.GetBytes(formdata.Substring(2));
else
formdataBytes = encoding.GetBytes(formdata);
//写入流
postStream.Write(formdataBytes, 0, formdataBytes.Length);
if (item.IsFile)
{
var bytes = item.GetFileBytes(encoding);
if (bytes == null)
{
this.PrintErrlog("读取文件错误:" + JsonHelper.SerializeObject(item));
throw new Exception("读取文件错误");
}
postStream.Write(bytes, 0, bytes.Length);
}
}
var footer = encoding.GetBytes("\r\n--" + boundary + "--\r\n");
postStream.Write(footer, 0, footer.Length);
byte[] buffer = StreamToBytes(postStream);
return buffer;
}
如果上传图片成功,服务器会返回一个MediaId,相当于图片已经成功上传到微信服务器了,这个就是图片的key
2.发送图片消息 webwxsendmsgimg
发送图片接口就比较简单了,和文字消息差不多,要改的就是Msg中的Type换成3,再加上刚才得到的MediaId,其他的都基本差不多,当返回的消息BaseResponse.Ret == 0 的时候,你就成功了
接下来那些发送小视频,声音等等的由于本人实际需求用不到,就没有继续写了.本来还想写个自动抢红包的,发现网页版根本不支持抢红包,就无从写起了...