您的位置:首页 > 移动开发 > 微信开发

C#微信公众号开发系列教程六(被动回复与上传下载多媒体文件)

2015-01-13 02:11 537 查看
微信公众号开发系列教程一(调试环境部署)

微信公众号开发系列教程一(调试环境部署续:vs远程调试)

C#微信公众号开发系列教程二(新手接入指南)

C#微信公众号开发系列教程三(消息体签名及加解密)

C#微信公众号开发系列教程四(接收普通消息)

C#微信公众号开发系列教程五(接收事件推送与消息排重)

C#微信公众号开发系列教程六(被动回复与上传下载多媒体文件)

第四,第五章已经讲了怎么处理用户发送的消息,本章就来讲讲怎么响应用户的请求。想必新手看到这个标题也就懵了,千万别懵,微信的接口就这样,在回复图片、音乐、语音等都需要将我们的媒体文件上传到微信的服务器才能使用。不知道这样的做法是出于什么考虑的,而且同是给用户回复消息,客服接口和群发接口发送的消息体格式竟然是不同的。估计是这几处接口不是同一个人写的,没有做好代码的统一,咱们屌丝开发者只能无力吐槽了。

在讲上传下载接口前,需要先将下先来讲讲access_token获取方法。在微信接口开发的过程access_token是至关重要的,是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。需要注意的时,一个公众号同时只存在一个有效的access_token,开发者需要在access_token过期前,刷新access_token。在刷新的过程中,公众平台后台会保证在刷新短时间内,新老access_token都可用,这保证了第三方业务的平滑过渡。

公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在微信公众平台官网-开发者中心页中获得(需要已经成为开发者,且帐号没有异常状态)。如下图:





获取access_token的接口地址是:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

将appid和secret替换成你自己的。

发送get请求到这个地址,返回的数据如下:

{"access_token":"eEd6dhp0s24JfWwDyGBbrvJxnhqHTSYZ8MKdQ7MuCGBKxAjHv-tEIwhFZzn102lGvIWxnjZZreT6C1NCT9fpS7NREOkEX42yojVnqKVaicg","expires_in":7200}

我们只需解析这个json,即可获取到我们所需的access_token.代码如下:

AccessToken实体类:


publicclassAccessToken
{
publicstringtoken{get;set;}
publicDateTimeexpirestime{get;set;}
}


获取accesstoken

///<summary>
///获取accesstoken
///</summary>
///<paramname="appid">第三方用户唯一凭证</param>
///<paramname="secret">第三方用户唯一凭证密钥,即appsecret</param>
///<returns>AccessToken对象,expirestime是过期时间</returns>
publicstaticAccessTokenGetAccessToken(stringappid,stringsecret)
{
try
{
stringurl=string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}",appid,secret);
stringretdata=Utils.HttpGet(url);
if(retdata.Contains("access_token"))
{
JObjectobj=(JObject)JsonConvert.DeserializeObject(retdata);
stringtoken=obj.Value<string>("access_token");
intexpirestime=obj.Value<int>("expires_in");
returnnewAccessToken{token=token,expirestime=DateTime.Now.AddSeconds(expirestime)};
}
else
{
WriteBug(retdata);//写错误日志
}
returnnull;
}
catch(Exceptione)
{
WriteBug(e.ToString());//写错误日志
returnnull;
}

}



access_token获取成功后,下面来讲上传下载多媒体文件吧。官方说,公众号在使用接口时,对多媒体文件、多媒体消息的获取和调用等操作,是通过media_id来进行的(咱读书少,不明白为什么不能使用url,而要多此一举先上传到服务器在发送)。通过本接口,公众号可以上传或下载多媒体文件。但请注意,每个多媒体文件(media_id)会在上传、用户发送到微信服务器3天后自动删除,以节省服务器资源。

上传多媒体的接口地址是:

http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE


其中access_token为调用接口凭证,type是媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)

注意事项:

上传的多媒体文件有格式和大小限制,如下:

图片(image):1M,支持JPG格式

语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式

视频(video):10MB,支持MP4格式

缩略图(thumb):64KB,支持JPG格式

媒体文件在后台保存时间为3天,即3天后media_id失效。

为了方便调用,将媒体文件的类型定义为枚举,代码如下:

publicenumMediaType
{
///<summary>
///图片(image):1M,支持JPG格式
///</summary>
image,
///<summary>
///语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
///</summary>
voice,
///<summary>
///视频(video):10MB,支持MP4格式
///</summary>
video,
///<summary>
///缩略图(thumb):64KB,支持JPG格式
///</summary>
thumb
}


然后定义返回值的类型:

publicclassUpLoadInfo
{
///<summary>
///媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb,主要用于视频与音乐格式的缩略图)
///</summary>
publicstringtype{get;set;}
///<summary>
///媒体文件上传后,获取时的唯一标识
///</summary>
publicstringmedia_id{get;set;}
///<summary>
///媒体文件上传时间戳
///</summary>
publicstringcreated_at{get;set;}
}


最后使用WebClient类来上传文件,并读出返回值,代码如下:

///<summary>
///微信上传多媒体文件
///</summary>
///<paramname="filepath">文件绝对路径</param>
publicstaticReceiveModel.UpLoadInfoWxUpLoad(stringfilepath,stringtoken,MediaTypemt)
{
using(WebClientclient=newWebClient())
{
byte[]b=client.UploadFile(string.Format("http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}",token,mt.ToString()),filepath);//调用接口上传文件
stringretdata=Encoding.Default.GetString(b);//获取返回值
if(retdata.Contains("media_id"))//判断返回值是否包含media_id,包含则说明上传成功,然后将返回的json字符串转换成json
{
returnJsonConvert.DeserializeObject<UpLoadInfo>(retdata);
}
else
{//否则,写错误日志

WriteBug(retdata);//写错误日志
returnnull;
}
}
}


至此,在讲回复消息之前,插入了两个基础支持接口,由于各位整理归纳能力太烂了,各位看官请多包涵,如有问题就留言和我交流。下面正式开始讲回复消息。在看下面内容的时候,请大家结合第四,第五章进行阅读。

前面两章讲述了接收并处理用户发送的消息,讲到了一个消息基类BaseMessage,而不管我们接收到什么类型的消息,都需要可以调用方法,进行响应用户的请求,所以,用户回复用户请求的方法需要封装到基类中。下面先简单了解下公众号可以回复的消息类型,以及消息格式。

注意:

一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:

1、开发者在5秒内未回复任何内容
2、开发者回复了异常数据,比如JSON数据等

[b]回复文本消息[/b]

<xml>
<ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
<FromUserName><![CDATA[开发者微信号]]></FromUserName>
<CreateTime>消息创建时间(整型)</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Content><![CDATA[回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)]]></Content>
</xml>


[b]回复图片消息[/b]

<xml>
<ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
<FromUserName><![CDATA[开发者微信号]]></FromUserName>
<CreateTime>消息创建时间(整型)</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId>
</Image>
</xml>


[b]回复语音消息[/b]

<xml>
<ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
<FromUserName><![CDATA[开发者微信号]]></FromUserName>
<CreateTime>消息创建时间(整型)</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<Voice>
<MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId>
</Voice>
</xml>


[b]回复视频消息[/b]

<xml>
<ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
<FromUserName><![CDATA[开发者微信号]]></FromUserName>
<CreateTime>消息创建时间(整型)</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<Video>
<MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId>
<Title><![CDATA[视频消息的标题]]></Title>

<Description><![CDATA[视频消息的描述]]></Description>

</Video>
</xml>


[b]回复音乐消息[/b]

<xml>
<ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
<FromUserName><![CDATA[开发者微信号]]></FromUserName>
<CreateTime>消息创建时间(整型)</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
<Music>
<ThumbMediaId><![CDATA[缩略图的媒体id,通过上传多媒体文件,得到的id。]]></ThumbMediaId>
<Title><![CDATA[视频消息的标题]]></Title>

<Description><![CDATA[视频消息的描述]]></Description>

<MusicURL><![CDATA[音乐链接]]></MusicURL>

<HQMusicUrl><![CDATA[高质量音乐链接,WIFI环境优先使用该链接播放音乐]]></HQMusicUrl>

</Music>
</xml>


[b]回复图文消息[/b]

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>2</ArticleCount>
<Articles>
<item>
<Title><![CDATA[title1]]></Title>
<Description><![CDATA[description1]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA</item>
<item>
<Title><![CDATA[title]]></Title>
<Description><![CDATA[description]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
</Articles>
</xml>


回复图文中,item是一个项,一个item代码一个图文。在响应的时候,我们只需根据数据格式,替换掉对应的属性,然后Response.Write(s)即可。结合前两章的讲解,BaseMessage的最终代码如下:

///<summary>
///消息体基类
///</summary>
publicabstractclassBaseMessage
{
///<summary>
///开发者微信号
///</summary>
publicstringToUserName{get;set;}
///<summary>
///发送方帐号(一个OpenID)
///</summary>
publicstringFromUserName{get;set;}
///<summary>
///消息创建时间(整型)
///</summary>
publicstringCreateTime{get;set;}
///<summary>
///消息类型
///</summary>
publicMsgTypeMsgType{get;set;}

publicvirtualvoidResponseNull()
{
Utils.ResponseWrite("");
}
publicvirtualvoidResText(EnterParamparam,stringcontent)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.AppendFormat("<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{0}]]></Content><FuncFlag>0</FuncFlag></xml>",content);
Response(param,resxml.ToString());
}
///<summary>
///回复消息(音乐)
///</summary>
publicvoidResMusic(EnterParamparam,Musicmu)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.Append("<MsgType><![CDATA[music]]></MsgType>");
resxml.AppendFormat("<Music><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description>",mu.Title,mu.Description);
resxml.AppendFormat("<MusicUrl><![CDATA[http://{0}{1}]]></MusicUrl><HQMusicUrl><![CDATA[http://{2}{3}]]></HQMusicUrl></Music><FuncFlag>0</FuncFlag></xml>",VqiRequest.GetCurrentFullHost(),mu.MusicUrl,VqiRequest.GetCurrentFullHost(),mu.HQMusicUrl);
Response(param,resxml.ToString());
}
publicvoidResVideo(EnterParamparam,Videov)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.Append("<MsgType><![CDATA[video]]></MsgType>");
resxml.AppendFormat("<Video><MediaId><![CDATA[{0}]]></MediaId>",v.media_id);
resxml.AppendFormat("<Title><![CDATA[{0}]]></Title>",v.title);
resxml.AppendFormat("<Description><![CDATA[{0}]]></Description></Video></xml>",v.description);
Response(param,resxml.ToString());
}

///<summary>
///回复消息(图片)
///</summary>
publicvoidResPicture(EnterParamparam,Picturepic,stringdomain)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.Append("<MsgType><![CDATA[image]]></MsgType>");
resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl></xml>",domain+pic.PictureUrl);
Response(param,resxml.ToString());
}

///<summary>
///回复消息(图文列表)
///</summary>
///<paramname="param"></param>
///<paramname="art"></param>
publicvoidResArticles(EnterParamparam,List<Articles>art)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.AppendFormat("<MsgType><![CDATA[news]]></MsgType><ArticleCount>{0}</ArticleCount><Articles>",art.Count);
for(inti=0;i<art.Count;i++)
{
resxml.AppendFormat("<item><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description>",art[i].Title,art[i].Description);
resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl><Url><![CDATA[{1}]]></Url></item>",art[i].PicUrl.Contains("http://")?art[i].PicUrl:"http://"+VqiRequest.GetCurrentFullHost()+art[i].PicUrl,art[i].Url.Contains("http://")?art[i].Url:"http://"+VqiRequest.GetCurrentFullHost()+art[i].Url);
}
resxml.Append("</Articles><FuncFlag>0</FuncFlag></xml>");
Response(param,resxml.ToString());
}
///<summary>
///多客服转发
///</summary>
///<paramname="param"></param>
publicvoidResDKF(EnterParamparam)
{
StringBuilderresxml=newStringBuilder();
resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);
resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);
resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType></xml>");
Response(param,resxml.ToString());
}
///<summary>
///多客服转发如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满),该用户会一直等待指定客服有接入能力后才会被接入,而不会被其他客服接待。建议在指定客服时,先查询客服的接入能力指定到有能力接入的客服,保证客户能够及时得到服务。
///</summary>
///<paramname="param">用户发送的消息体</param>
///<paramname="KfAccount">多客服账号</param>
publicvoidResDKF(EnterParamparam,stringKfAccount)
{
StringBuilderresxml=newStringBuilder();
resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);
resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);
resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType><TransInfo><KfAccount>{0}</KfAccount></TransInfo></xml>",KfAccount);
Response(param,resxml.ToString());
}
privatevoidResponse(EnterParamparam,stringdata)
{
if(param.IsAes)
{
varwxcpt=newMsgCrypt(param.token,param.EncodingAESKey,param.appid);
wxcpt.EncryptMsg(data,Utils.ConvertDateTimeInt(DateTime.Now).ToString(),Utils.GetRamCode(),refdata);
}
Utils.ResponseWrite(data);

}
}


上面的代码中,publicvoidResDKF(EnterParamparam),publicvoidResDKF(EnterParamparam,stringKfAccount)两个方法时多客服中,用户转发用户发送的消息的,多客服将在后期的博文中进行更新,敬请期待。

publicvoidResMusic(EnterParamparam,Musicmu)方法中的Music类的定义如下:

publicclassMusic
{
#region属性
///<summary>
///音乐链接
///</summary>
publicstringMusicUrl{get;set;}
///<summary>
///高质量音乐链接,WIFI环境优先使用该链接播放音乐
///</summary>
publicstringHQMusicUrl{get;set;}
///<summary>
///标题
///</summary>
publicstringTitle{get;set;}
///<summary>
///描述
///</summary>
publicstringDescription{get;set;}
#endregion
}


publicvoidResVideo(EnterParamparam,Videov)方法中的Video类的定义如下:

publicclassVideo
{
publicstringtitle{get;set;}
publicstringmedia_id{get;set;}
publicstringdescription{get;set;}
}


publicvoidResArticles(EnterParamparam,List<Articles>art)中的Articles定义如下:

publicclassArticles
{
#region属性
///<summary>
///图文消息标题
///</summary>
publicstringTitle{get;set;}
///<summary>
///图文消息描述
///</summary>
publicstringDescription{get;set;}
///<summary>
///图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80。
///</summary>
publicstringPicUrl{get;set;}
///<summary>
///点击图文消息跳转链接
///</summary>
publicstringUrl{get;set;}
#endregion
}


至此,此章结束。

时间仓促,如有不明白的,请留言,如果你觉得本篇博文对你有帮助,请点击一下推荐,推荐给更多的朋友的。

各位有建议或者意见可留言给我哦,或者加如QQ群一起进行交流。[url=http://shang.qq.com/wpa/qunwpa?idkey=3deb873ae5dd8eb1dc216ef12b681d3fc7d30cc172c77a979cd44d305c9cf92d]

"target=_blank>]></Url>
</item>
<item>
<Title><![CDATA[title]]></Title>
<Description><![CDATA[description]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
</Articles>
</xml>[/code]

回复图文中,item是一个项,一个item代码一个图文。在响应的时候,我们只需根据数据格式,替换掉对应的属性,然后Response.Write(s)即可。结合前两章的讲解,BaseMessage的最终代码如下:

///<summary>
///消息体基类
///</summary>
publicabstractclassBaseMessage
{
///<summary>
///开发者微信号
///</summary>
publicstringToUserName{get;set;}
///<summary>
///发送方帐号(一个OpenID)
///</summary>
publicstringFromUserName{get;set;}
///<summary>
///消息创建时间(整型)
///</summary>
publicstringCreateTime{get;set;}
///<summary>
///消息类型
///</summary>
publicMsgTypeMsgType{get;set;}

publicvirtualvoidResponseNull()
{
Utils.ResponseWrite("");
}
publicvirtualvoidResText(EnterParamparam,stringcontent)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.AppendFormat("<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{0}]]></Content><FuncFlag>0</FuncFlag></xml>",content);
Response(param,resxml.ToString());
}
///<summary>
///回复消息(音乐)
///</summary>
publicvoidResMusic(EnterParamparam,Musicmu)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.Append("<MsgType><![CDATA[music]]></MsgType>");
resxml.AppendFormat("<Music><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description>",mu.Title,mu.Description);
resxml.AppendFormat("<MusicUrl><![CDATA[http://{0}{1}]]></MusicUrl><HQMusicUrl><![CDATA[http://{2}{3}]]></HQMusicUrl></Music><FuncFlag>0</FuncFlag></xml>",VqiRequest.GetCurrentFullHost(),mu.MusicUrl,VqiRequest.GetCurrentFullHost(),mu.HQMusicUrl);
Response(param,resxml.ToString());
}
publicvoidResVideo(EnterParamparam,Videov)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.Append("<MsgType><![CDATA[video]]></MsgType>");
resxml.AppendFormat("<Video><MediaId><![CDATA[{0}]]></MediaId>",v.media_id);
resxml.AppendFormat("<Title><![CDATA[{0}]]></Title>",v.title);
resxml.AppendFormat("<Description><![CDATA[{0}]]></Description></Video></xml>",v.description);
Response(param,resxml.ToString());
}

///<summary>
///回复消息(图片)
///</summary>
publicvoidResPicture(EnterParamparam,Picturepic,stringdomain)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.Append("<MsgType><![CDATA[image]]></MsgType>");
resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl></xml>",domain+pic.PictureUrl);
Response(param,resxml.ToString());
}

///<summary>
///回复消息(图文列表)
///</summary>
///<paramname="param"></param>
///<paramname="art"></param>
publicvoidResArticles(EnterParamparam,List<Articles>art)
{
StringBuilderresxml=newStringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName,Utils.ConvertDateTimeInt(DateTime.Now)));
resxml.AppendFormat("<MsgType><![CDATA[news]]></MsgType><ArticleCount>{0}</ArticleCount><Articles>",art.Count);
for(inti=0;i<art.Count;i++)
{
resxml.AppendFormat("<item><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description>",art[i].Title,art[i].Description);
resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl><Url><![CDATA[{1}]]></Url></item>",art[i].PicUrl.Contains("http://")?art[i].PicUrl:"http://"+VqiRequest.GetCurrentFullHost()+art[i].PicUrl,art[i].Url.Contains("http://")?art[i].Url:"http://"+VqiRequest.GetCurrentFullHost()+art[i].Url);
}
resxml.Append("</Articles><FuncFlag>0</FuncFlag></xml>");
Response(param,resxml.ToString());
}
///<summary>
///多客服转发
///</summary>
///<paramname="param"></param>
publicvoidResDKF(EnterParamparam)
{
StringBuilderresxml=newStringBuilder();
resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);
resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);
resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType></xml>");
Response(param,resxml.ToString());
}
///<summary>
///多客服转发如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满),该用户会一直等待指定客服有接入能力后才会被接入,而不会被其他客服接待。建议在指定客服时,先查询客服的接入能力指定到有能力接入的客服,保证客户能够及时得到服务。
///</summary>
///<paramname="param">用户发送的消息体</param>
///<paramname="KfAccount">多客服账号</param>
publicvoidResDKF(EnterParamparam,stringKfAccount)
{
StringBuilderresxml=newStringBuilder();
resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);
resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);
resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType><TransInfo><KfAccount>{0}</KfAccount></TransInfo></xml>",KfAccount);
Response(param,resxml.ToString());
}
privatevoidResponse(EnterParamparam,stringdata)
{
if(param.IsAes)
{
varwxcpt=newMsgCrypt(param.token,param.EncodingAESKey,param.appid);
wxcpt.EncryptMsg(data,Utils.ConvertDateTimeInt(DateTime.Now).ToString(),Utils.GetRamCode(),refdata);
}
Utils.ResponseWrite(data);

}
}


上面的代码中,publicvoidResDKF(EnterParamparam),publicvoidResDKF(EnterParamparam,stringKfAccount)两个方法时多客服中,用户转发用户发送的消息的,多客服将在后期的博文中进行更新,敬请期待。

publicvoidResMusic(EnterParamparam,Musicmu)方法中的Music类的定义如下:

publicclassMusic
{
#region属性
///<summary>
///音乐链接
///</summary>
publicstringMusicUrl{get;set;}
///<summary>
///高质量音乐链接,WIFI环境优先使用该链接播放音乐
///</summary>
publicstringHQMusicUrl{get;set;}
///<summary>
///标题
///</summary>
publicstringTitle{get;set;}
///<summary>
///描述
///</summary>
publicstringDescription{get;set;}
#endregion
}


publicvoidResVideo(EnterParamparam,Videov)方法中的Video类的定义如下:

publicclassVideo
{
publicstringtitle{get;set;}
publicstringmedia_id{get;set;}
publicstringdescription{get;set;}
}


publicvoidResArticles(EnterParamparam,List<Articles>art)中的Articles定义如下:

publicclassArticles
{
#region属性
///<summary>
///图文消息标题
///</summary>
publicstringTitle{get;set;}
///<summary>
///图文消息描述
///</summary>
publicstringDescription{get;set;}
///<summary>
///图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80。
///</summary>
publicstringPicUrl{get;set;}
///<summary>
///点击图文消息跳转链接
///</summary>
publicstringUrl{get;set;}
#endregion
}


至此,此章结束。

时间仓促,如有不明白的,请留言,如果你觉得本篇博文对你有帮助,请点击一下推荐,推荐给更多的朋友的。

各位有建议或者意见可留言给我哦,或者加如QQ群一起进行交流。[url=http://shang.qq.com/wpa/qunwpa?idkey=3deb873ae5dd8eb1dc216ef12b681d3fc7d30cc172c77a979cd44d305c9cf92d]



如果你是土豪,可以扫描下面的二维码悬赏一下,你的支持是笔者继续更新下去的动力。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: