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

微信公众号开发系列教程一(调试环境部署续: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的接口地址是:

  1. https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
  1. appidsecret替换成你自己的。

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

  1. {"access_token":"eEd6dhp0s24JfWwDyGBbrvJxnhqHTSYZ8MKdQ7MuCGBKxAjHv-tEIwhFZzn102lGvIWxnjZZreT6C1NCT9fpS7NREOkEX42yojVnqKVaicg","expires_in":7200}
  1. 我们只需解析这个json,即可获取到我们所需的access_token.代码如下:
  1. AccessToken实体类:
  1. public class AccessToken
  2. {
  3. public string token { get; set; }
  4. public DateTime expirestime { get; set; }
  5. }

获取access token

  1. /// <summary>
  2. /// 获取access token
  3. /// </summary>
  4. /// <param name="appid">第三方用户唯一凭证</param>
  5. /// <param name="secret">第三方用户唯一凭证密钥,即appsecret</param>
  6. /// <returns>AccessToken对象,expirestime是过期时间</returns>
  7. public static AccessToken GetAccessToken(string appid, string secret)
  8. {
  9. try
  10. {
  11. string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, secret);
  12. string retdata = Utils.HttpGet(url);
  13. if (retdata.Contains("access_token"))
  14. {
  15. JObject obj = (JObject)JsonConvert.DeserializeObject(retdata);
  16. string token = obj.Value<string>("access_token");
  17. int expirestime = obj.Value<int>("expires_in");
  18. return new AccessToken { token = token, expirestime = DateTime.Now.AddSeconds(expirestime) };
  19. }
  20. else
  21. {
  22. WriteBug(retdata);//写错误日志
  23. }
  24. return null;
  25. }
  26. catch (Exception e)
  27. {
  28. WriteBug(e.ToString());//写错误日志
  29. return null;
  30. }
  31.  
  32. }
  1.  

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

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

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

其中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失效。

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

  1. public enum MediaType
  2. {
  3. /// <summary>
  4. /// 图片(image): 1M,支持JPG格式
  5. /// </summary>
  6. image,
  7. /// <summary>
  8. /// 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
  9. /// </summary>
  10. voice,
  11. /// <summary>
  12. /// 视频(video):10MB,支持MP4格式
  13. /// </summary>
  14. video,
  15. /// <summary>
  16. /// 缩略图(thumb):64KB,支持JPG格式
  17. /// </summary>
  18. thumb
  19. }

然后定义返回值的类型:

  1. public class UpLoadInfo
  2. {
  3. /// <summary>
  4. /// 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb,主要用于视频与音乐格式的缩略图)
  5. /// </summary>
  6. public string type { get; set; }
  7. /// <summary>
  8. /// 媒体文件上传后,获取时的唯一标识
  9. /// </summary>
  10. public string media_id { get; set; }
  11. /// <summary>
  12. /// 媒体文件上传时间戳
  13. /// </summary>
  14. public string created_at { get; set; }
  15. }

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

  1. /// <summary>
  2. /// 微信上传多媒体文件
  3. /// </summary>
  4. /// <param name="filepath">文件绝对路径</param>
  5. public static ReceiveModel.UpLoadInfo WxUpLoad(string filepath, string token, MediaType mt)
  6. {
  7. using (WebClient client = new WebClient())
  8. {
  9. 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);//调用接口上传文件
  10. string retdata = Encoding.Default.GetString(b);//获取返回值
  11. if (retdata.Contains("media_id"))//判断返回值是否包含media_id,包含则说明上传成功,然后将返回的json字符串转换成json
  12. {
  13. return JsonConvert.DeserializeObject<UpLoadInfo>(retdata);
  14. }
  15. else
  16. {//否则,写错误日志
  17.  
  18. WriteBug(retdata);//写错误日志
  19. return null;
  20. }
  21. }
  22. }

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

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

注意:

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

  1. 1、开发者在5秒内未回复任何内容
  2. 2、开发者回复了异常数据,比如JSON数据等
回复文本消息
  1. <xml>
  2. <ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
  3. <FromUserName><![CDATA[开发者微信号]]></FromUserName>
  4. <CreateTime>消息创建时间 (整型)</CreateTime>
  5. <MsgType><![CDATA[image]]></MsgType>
  6. <Content><![CDATA[回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)]]></Content>
  7. </xml>
回复图片消息
  1. <xml>
  2. <ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
  3. <FromUserName><![CDATA[开发者微信号]]></FromUserName>
  4. <CreateTime>消息创建时间 (整型)</CreateTime>
  5. <MsgType><![CDATA[image]]></MsgType>
  6. <Image>
  7. <MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId>
  8. </Image>
  9. </xml>
回复语音消息
  1. <xml>
  2. <ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
  3. <FromUserName><![CDATA[开发者微信号]]></FromUserName>
  4. <CreateTime>消息创建时间 (整型)</CreateTime>
  5. <MsgType><![CDATA[voice]]></MsgType>
  6. <Voice>
  7. <MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId>
  8. </Voice>
  9. </xml>
回复视频消息
  1. <xml>
  2. <ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
  3. <FromUserName><![CDATA[开发者微信号]]></FromUserName>
  4. <CreateTime>消息创建时间 (整型)</CreateTime>
  5. <MsgType><![CDATA[video]]></MsgType>
  6. <Video>
  7. <MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId>
  8. <Title><![CDATA[视频消息的标题]]></Title>
  1. <Description><![CDATA[视频消息的描述]]></Description>
  1. </Video>
  2. </xml>
回复音乐消息
  1. <xml>
  2. <ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName>
  3. <FromUserName><![CDATA[开发者微信号]]></FromUserName>
  4. <CreateTime>消息创建时间 (整型)</CreateTime>
  5. <MsgType><![CDATA[music]]></MsgType>
  6. <Music>
  7. <ThumbMediaId><![CDATA[缩略图的媒体id,通过上传多媒体文件,得到的id。]]></ThumbMediaId>
  8. <Title><![CDATA[视频消息的标题]]></Title>
  1. <Description><![CDATA[视频消息的描述]]></Description>
  1. <MusicURL><![CDATA[音乐链接]]></MusicURL>
  1. <HQMusicUrl><![CDATA[高质量音乐链接,WIFI环境优先使用该链接播放音乐]]></HQMusicUrl>
  1. </Music>
  2. </xml>
回复图文消息
  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[fromUser]]></FromUserName>
  4. <CreateTime>12345678</CreateTime>
  5. <MsgType><![CDATA[news]]></MsgType>
  6. <ArticleCount>2</ArticleCount>
  7. <Articles>
  8. <item>
  9. <Title><![CDATA[title1]]></Title>
  10. <Description><![CDATA[description1]]></Description>
  11. <PicUrl><![CDATA[picurl]]></PicUrl>
  12. <Url><![CDATA[url]]></Url>
  13. </item>
  14. <item>
  15. <Title><![CDATA[title]]></Title>
  16. <Description><![CDATA[description]]></Description>
  17. <PicUrl><![CDATA[picurl]]></PicUrl>
  18. <Url><![CDATA[url]]></Url>
  19. </item>
  20. </Articles>
  21. </xml>

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

  1. /// <summary>
  2. /// 消息体基类
  3. /// </summary>
  4. public abstract class BaseMessage
  5. {
  6. /// <summary>
  7. /// 开发者微信号
  8. /// </summary>
  9. public string ToUserName { get; set; }
  10. /// <summary>
  11. /// 发送方帐号(一个OpenID)
  12. /// </summary>
  13. public string FromUserName { get; set; }
  14. /// <summary>
  15. /// 消息创建时间 (整型)
  16. /// </summary>
  17. public string CreateTime { get; set; }
  18. /// <summary>
  19. /// 消息类型
  20. /// </summary>
  21. public MsgType MsgType { get; set; }
  22.  
  23. public virtual void ResponseNull()
  24. {
  25. Utils.ResponseWrite("");
  26. }
  27. public virtual void ResText(EnterParam param, string content)
  28. {
  29. StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>", FromUserName, ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));
  30. resxml.AppendFormat("<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{0}]]></Content><FuncFlag>0</FuncFlag></xml>", content);
  31. Response(param, resxml.ToString());
  32. }
  33. /// <summary>
  34. /// 回复消息(音乐)
  35. /// </summary>
  36. public void ResMusic(EnterParam param, Music mu)
  37. {
  38. StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));
  39. resxml.Append(" <MsgType><![CDATA[music]]></MsgType>");
  40. resxml.AppendFormat("<Music><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description>", mu.Title, mu.Description);
  41. 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);
  42. Response(param, resxml.ToString());
  43. }
  44. public void ResVideo(EnterParam param, Video v)
  45. {
  46. StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));
  47. resxml.Append(" <MsgType><![CDATA[video]]></MsgType>");
  48. resxml.AppendFormat("<Video><MediaId><![CDATA[{0}]]></MediaId>", v.media_id);
  49. resxml.AppendFormat("<Title><![CDATA[{0}]]></Title>", v.title);
  50. resxml.AppendFormat("<Description><![CDATA[{0}]]></Description></Video></xml>", v.description);
  51. Response(param, resxml.ToString());
  52. }
  53.  
  54. /// <summary>
  55. /// 回复消息(图片)
  56. /// </summary>
  57. public void ResPicture(EnterParam param, Picture pic, string domain)
  58. {
  59. StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));
  60. resxml.Append(" <MsgType><![CDATA[image]]></MsgType>");
  61. resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl></xml>", domain + pic.PictureUrl);
  62. Response(param, resxml.ToString());
  63. }
  64.  
  65. /// <summary>
  66. /// 回复消息(图文列表)
  67. /// </summary>
  68. /// <param name="param"></param>
  69. /// <param name="art"></param>
  70. public void ResArticles(EnterParam param, List<Articles> art)
  71. {
  72. StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now)));
  73. resxml.AppendFormat("<MsgType><![CDATA[news]]></MsgType><ArticleCount>{0}</ArticleCount><Articles>", art.Count);
  74. for (int i = ; i < art.Count; i++)
  75. {
  76. resxml.AppendFormat("<item><Title><![CDATA[{0}]]></Title> <Description><![CDATA[{1}]]></Description>", art[i].Title, art[i].Description);
  77. 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);
  78. }
  79. resxml.Append("</Articles><FuncFlag>0</FuncFlag></xml>");
  80. Response(param, resxml.ToString());
  81. }
  82. /// <summary>
  83. /// 多客服转发
  84. /// </summary>
  85. /// <param name="param"></param>
  86. public void ResDKF(EnterParam param)
  87. {
  88. StringBuilder resxml = new StringBuilder();
  89. resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);
  90. resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);
  91. resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType></xml>");
  92. Response(param, resxml.ToString());
  93. }
  94. /// <summary>
  95. /// 多客服转发如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满),该用户会一直等待指定客服有接入能力后才会被接入,而不会被其他客服接待。建议在指定客服时,先查询客服的接入能力指定到有能力接入的客服,保证客户能够及时得到服务。
  96. /// </summary>
  97. /// <param name="param">用户发送的消息体</param>
  98. /// <param name="KfAccount">多客服账号</param>
  99. public void ResDKF(EnterParam param, string KfAccount)
  100. {
  101. StringBuilder resxml = new StringBuilder();
  102. resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName);
  103. resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime);
  104. resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType><TransInfo><KfAccount>{0}</KfAccount></TransInfo></xml>", KfAccount);
  105. Response(param, resxml.ToString());
  106. }
  107. private void Response(EnterParam param, string data)
  108. {
  109. if (param.IsAes)
  110. {
  111. var wxcpt = new MsgCrypt(param.token, param.EncodingAESKey, param.appid);
  112. wxcpt.EncryptMsg(data, Utils.ConvertDateTimeInt(DateTime.Now).ToString(), Utils.GetRamCode(), ref data);
  113. }
  114. Utils.ResponseWrite(data);
  115.  
  116. }
  117. }

上面的代码中,public  void ResDKF(EnterParam param),public  void ResDKF(EnterParam param, string KfAccount)两个方法时多客服中,用户转发用户发送的消息的,多客服将在后期的博文中进行更新,敬请期待。

public  void ResMusic(EnterParam param, Music mu)方法中的Music类的定义如下:

  1. public class Music
  2. {
  3. #region 属性
  4. /// <summary>
  5. /// 音乐链接
  6. /// </summary>
  7. public string MusicUrl { get; set; }
  8. /// <summary>
  9. /// 高质量音乐链接,WIFI环境优先使用该链接播放音乐
  10. /// </summary>
  11. public string HQMusicUrl { get; set; }
  12. /// <summary>
  13. /// 标题
  14. /// </summary>
  15. public string Title { get; set; }
  16. /// <summary>
  17. /// 描述
  18. /// </summary>
  19. public string Description { get; set; }
  20. #endregion
  21. }

public  void ResVideo(EnterParam param, Video v)方法中的Video类的定义如下:

  1. public class Video
  2. {
  3. public string title { get; set; }
  4. public string media_id { get; set; }
  5. public string description { get; set; }
  6. }

public  void ResArticles(EnterParam param, List<Articles> art)中的Articles定义如下:

  1. public class Articles
  2. {
  3. #region 属性
  4. /// <summary>
  5. /// 图文消息标题
  6. /// </summary>
  7. public string Title { get; set; }
  8. /// <summary>
  9. /// 图文消息描述
  10. /// </summary>
  11. public string Description { get; set; }
  12. /// <summary>
  13. /// 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80。
  14. /// </summary>
  15. public string PicUrl { get; set; }
  16. /// <summary>
  17. /// 点击图文消息跳转链接
  18. /// </summary>
  19. public string Url { get; set; }
  20. #endregion
  21. }

至此,此章结束。

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

各位有建议或者意见可留言给我哦,或者加如QQ群一起进行交流。

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

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

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

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

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

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

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

    http://www.cnblogs.com/zskbll/p/4139039.html C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C ...

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

    http://www.cnblogs.com/zskbll/p/4093954.html 此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可 ...

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

    http://www.cnblogs.com/zskbll/p/4080328.html 目录 C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试 ...

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

    微信服务器在5秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次.这样的话,问题就来了.有这样一个场景:当用户关注微信账号时,获取当前用户信息,然后将信息写到数据库中.类似于pc端网站的注册.可 ...

  7. C#微信公众号开发入门教程

    首先打开开发文档: 微信公众号开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 一.创建测试账号 可以先申请一个开发者测试账号

  8. 微信公众号开发系列-13、基于RDIFramework.NET框架整合微信开发应用效果展示

    1.前言 通过前面一系列文章的学习,我们对微信公众号开发已经有了一个比较深入和全面的了解. 微信公众号开发为企业解决那些问题呢? 我们经常看到微信公众号定制开发.微信公众平台定制开发,都不知道这些能给 ...

  9. 微信公众号开发系列-获取微信OpenID

    在微信开发时候在做消息接口交互的时候须要使用带微信加密ID(OpenId),下面讲讲述2中类型方式获取微信OpenID.接收事件推送方式和网页授权获取用户基本信息方式获取. 1.通过接收被动消息方式获 ...

随机推荐

  1. Fourth glance in Go

    在Go里面的结构体和方法是很有意思的内容.它即和OO有点像,但又不完全一样.为什么这么说呢?当你把结构体映射为OO里面的类的时候,你给结构体添加方法,你就会发现其实方法与结构体并没有严格意义上的关系. ...

  2. 时间同步出现ntpdate[1788]: the NTP socket is in use, exiting

    问题: [root@service ~]# ntpdate ntp.api.bz 17 Jun 19:22:23 ntpdate[2701]: the NTP socket is in use, ex ...

  3. PADS_AD_Cadence转换

    PADS_AD_Cadence转换 软件版本:PADS的版本是PADS9.5,Altium designer的版本是Altium designer winter 09 PADS和AD的转换 PADS的 ...

  4. Windows 10 Threshold 2 升级记录

    昨天(11月17日)升级到Windows 10 Threshold 2版本.我的使用的设备是Surface Pro 3,4G内存,128G硬盘. Threshold 2是作为一个Windows系统更新 ...

  5. Spring学习之第一个Spring MVC程序(IDEA开发环境)

    回顾Java平台上Web开发历程来看,从Servlet出现开始,到JSP繁盛一时,然后是Servlet+JSP时代,最后演化为现在Web开发框架盛行的时代.一般接触到一个新的Web框架,都会想问这个框 ...

  6. UVa10820 Send a Table[欧拉函数]

    Send a TableInput: Standard Input Output: Standard Output When participating in programming contests ...

  7. ubuntu在命令行新建用户后无法进入桌面的原因

    在命名行模式下 用useradd新建一个用户后 在图形界面输入密码无法登陆 这是因为未对新建的用户进行任何配置 用adduser命令新建用户即可进入桌面 下面说一下useradd 和 adduser的 ...

  8. 斗地主(Noip2015Day1T3)

    题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...

  9. webpack常用加载器和插件

    css文件加载器: style-loader,css-loader,sass-loader,less-loader //style和css加载器必须放在一起使用,且style必须放前面(style!c ...

  10. sublime text2安装package control的方法

    Package Control 方法一:在线安装,首先打开 Ctrl + ~,输入如下的代码: import urllib2,os; pf='Package Control.sublime-packa ...