微信开发者模式下添加素材_微信开发工具 添加 企业微信小程序模式 - CSDN
  • * 获取素材列表 */ public JSONObject getMaterialList(String type ,int offset, int count) { String requestUrl = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_to
    /**
         * 获取素材列表
         */
        public JSONObject getMaterialList(String type ,int offset, int count) {
            String requestUrl = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=" + ACCESS_TOKEN;
            String outputStr = "";
            //POST请求发送的json参数
            Material material = new Material();
            material.setType(type);
            material.setOffset(offset);
            material.setCount(count);
    
            JSONObject jsonObject = new JSONObject();
            jsonObject = JSONObject.fromObject(material);
            System.out.println(jsonObject);
    
            outputStr = jsonObject.toString();
    
            new HttpRequestPost();
            jsonObject = HttpRequestPost.httpRequest(requestUrl, outputStr, "POST");
            return jsonObject;
        }

    获取image素材返回的json格式
    这里写图片描述
    获取news素材返回的json格式
    这里写图片描述
    解析json返回值

    /**
         * 解析getMaterialList获取的json数据 to list for news
         * 
         * @param jsonObject
         * @return
         */
        public List<MaterialNews> MyJsonToObject(JSONObject jsonObject) {
            JSONArray jsonArray = jsonObject.getJSONArray("item");
            System.out.println(jsonArray);
    
            List<MaterialNews> lists = new ArrayList<MaterialNews>();
            System.out.println(jsonArray.size());
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject json = (JSONObject) jsonArray.get(i);
                json = json.getJSONObject("content");
                System.out.println(json);
    
                JSONArray arr = json.getJSONArray("news_item");
                json = (JSONObject) arr.get(0);
    
                MaterialNews news = new MaterialNews();
                String title = json.getString("title");
                String author = json.getString("author");
                String digest = json.getString("digest");
                String thumb_media_id = json.getString("thumb_media_id");
                System.out.println(thumb_media_id);
                String url = json.getString("url");
                String content = json.getString("content");
                news.setTitle(title);
                news.setAuthor(author);
                news.setDigest(digest);
                news.setThumb_media_id(thumb_media_id);
                news.setUrl(url);
                news.setContent("NOTNEED");
                lists.add(news);
            }
            return lists;
        }
    
        /**
         * 解析getMaterialList获取的json数据 to list for image
         * 
         * @param jsonObject
         * @return
         */
        public List<MaterialImage> ImageMyJsonToObject(JSONObject jsonObject) {
            List<MaterialImage> list = new ArrayList<MaterialImage>();
            JSONArray jsonArray = jsonObject.getJSONArray("item");
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject json = (JSONObject) jsonArray.get(i);
                MaterialImage image = new MaterialImage();
                image.setMedia_id(json.getString("media_id"));
                image.setName(json.getString("name"));
                try {
                    /**旧的image 没有url 需处理异常 新添加的有url*/
                    image.setUrl(json.getString("url"));
                } catch (Exception e) {
                    System.out.println("url 不存在异常");
                }
                list.add(image);
            }
            return list;
        }
    展开全文
  • 微信公众号平台是可以直接把音频素材插入到图文消息里面。但是现在自己开发的微信管理平台无法在上传的图文素材中插入音频。试过audio标签,上传后audio标签就没了,不知道是不是腾讯屏蔽了。 请教一下怎么在开发...
  • 微信开发者模式下的功能之一获取素材列表并保存的方法了解一下: 写这个方法肯定也是根据微信开发文档说明总结出获取的方法,首先先看微信开发文档给出的内容获取方法接口提示: 先给个链接地址:...

    微信开发者模式下的功能之一获取素材列表并保存的方法了解一下

    写这个方法肯定也是根据微信开发文档说明总结出获取的方法,首先先看微信开发文档给出的内容获取方法接口提示:

    先给个链接地址https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738734

    首先文档主要部分接口参数说明

    这里建议需要调用的接口请求链接为了防止错误最好还是自己复制下来用,请注意请求方式“POST”和请求的协议。

    接下来时文档给出的获取列表的返回形式:

    返回形式中的参数说明:

    好了,这就是微信开发文档中给出的所有获取素材列表的说明了,接下来我们要根据这些说明自己定义一个方法去实现这个过程,直接上代码:

    首先在开发工具中顶一个通用工具类:CommonUtil.java,在这里面实现所需要的方法:

     1 import org.slf4j.Logger;
     2 import org.slf4j.LoggerFactory;
     3 
     4 
     5 /**
     6  * 通用工具类
     7  * @author Admin
     8  *
     9  */
    10 public class CommonUtil {
    11     private static Logger log = LoggerFactory.getLogger(CommonUtil.class);//定义日志获取状态输出
    12 
    13     // 凭证获取
    14   //获取access_token
    15     public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    16     //获取素材列表
    17     public final static String MATERIAL = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN";
    18     
    19    
    20 }

    这个工具类大体就是这个样式,该有的说明我都标注了,所需要调用的接口请直接复制即可,避免出错。

    微信公众号开发都是需要调取接口的,在这个公共工具类中首先先写一个发送https请求的方法

     1 /**
     2      * 发送https请求
     3      * 
     4      * @param requestUrl 请求地址
     5      * @param requestMethod 请求方式(GET、POST)
     6      * @param outputStr 提交的数据
     7      * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     8      */
     9     public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
    10         JSONObject jsonObject = null;
    11         try {
    12             // 创建SSLContext对象,并使用我们指定的信任管理器初始化
    13             TrustManager[] tm = { new MyX509TrustManager() };
    14             SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
    15             sslContext.init(null, tm, new java.security.SecureRandom());
    16             // 从上述SSLContext对象中得到SSLSocketFactory对象
    17             SSLSocketFactory ssf = sslContext.getSocketFactory();
    18 
    19             URL url = new URL(requestUrl);
    20             HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    21             conn.setSSLSocketFactory(ssf);
    22             
    23             conn.setDoOutput(true);
    24             conn.setDoInput(true);
    25             conn.setUseCaches(false);
    26             // 设置请求方式(GET/POST)
    27             conn.setRequestMethod(requestMethod);
    28 
    29             // 当outputStr不为null时向输出流写数据
    30             if (null != outputStr) {
    31                 OutputStream outputStream = conn.getOutputStream();
    32                 // 注意编码格式
    33                 outputStream.write(outputStr.getBytes("UTF-8"));
    34                 outputStream.close();
    35             }
    36 
    37             // 从输入流读取返回内容
    38             InputStream inputStream = conn.getInputStream();
    39             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
    40             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
    41             String str = null;
    42             StringBuffer buffer = new StringBuffer();
    43             while ((str = bufferedReader.readLine()) != null) {
    44                 buffer.append(str);
    45             }
    46 
    47             // 释放资源
    48             bufferedReader.close();
    49             inputStreamReader.close();
    50             inputStream.close();
    51             inputStream = null;
    52             conn.disconnect();
    53             jsonObject = JSONObject.fromObject(buffer.toString());
    54         } catch (ConnectException ce) {
    55             log.error("连接超时:{}", ce);
    56         } catch (Exception e) {
    57             log.error("https请求异常:{}", e);
    58         }
    59         return jsonObject;
    60     }

    然后是获取素材列表所需要的方法(这里是获取的图文消息):

     1 /**
     2      * 获取素材列表并存入集合中
     3      * @param accessToken 获取接口凭证的唯一标识
     4      * @param type 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
     5      * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
     6      * @param count 返回素材的数量,取值在1到20之间
     7      * @return
     8      */
     9     public static List<Material> getMaterial(String accessToken,String type,int offset,int count) { 
    10         List<Material> lists = new ArrayList<Material>();//定义图文素材实体类集合
    11         String outputStr="";//定义一个空的参数字符串
    12         String requestUrl = MATERIAL.replace("ACCESS_TOKEN", accessToken);//替换调access_token
    13         MaterialParam para = new MaterialParam();//调用接口所需要的参数实体类
    14         para.setType(type);
    15         para.setOffset(offset);
    16         para.setCount(count);
    17         JSONObject jsonObject = new JSONObject();
    18         jsonObject = JSONObject.fromObject(para);
    19         outputStr = jsonObject.toString();//将参数对象转换成json字符串
    20 
    21         jsonObject = httpsRequest(requestUrl, "POST", outputStr);  //发送https请求(请求的路径,方式,所携带的参数)
    22         // 如果请求成功  
    23         if (null != jsonObject) {
    24             try {  
    25                 JSONArray jsonArray = jsonObject.getJSONArray("item");
    26                 for (int i = 0; i < jsonArray.size(); i++) {
    27                     JSONObject json = (JSONObject) jsonArray.get(i);
    28                     json = json.getJSONObject("content");
    29                     System.out.println(json);
    30 
    31                     JSONArray arr = json.getJSONArray("news_item");
    32                     json = (JSONObject) arr.get(0);
    33 
    34                     Material material = new Material();
    35                     String title = json.getString("title");
    36                     String author = json.getString("author");
    37                     String digest = json.getString("digest");
    38                     String thumb_media_id = json.getString("thumb_media_id");
    39                     //System.out.println(thumb_media_id);
    40                     String url = json.getString("url");
    41                     String content = json.getString("content");
    42                     material.setTitle(title);
    43                     material.setAuthor(author);
    44                     material.setDigest(digest);
    45                     material.setThumb_media_id(thumb_media_id);
    46                     material.setUrl(url);
    47                     material.setContent(content);
    48                     material.setShow_cover_pic(1);
    49                     lists.add(material);
    50                 }
    51             } catch (JSONException e) {  
    52                 accessToken = null;  
    53                 // 获取Material失败  
    54                 log.error("获取Material失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
    55             }  
    56         }  
    57         return lists;  
    58     }  

    上面所有的方法说明均已备注上,里面的用到的实体类为:

    获取素材列表参数实体类Material.java

     1 package com.shihe.shcoud.utils.pojo;
     2 /*获取素材列表参数实体类**/
     3 public class Material {
     4     
     5     private String title;//图文消息的标题
     6     
     7     private String thumb_media_id;//图文消息的封面图片素材id(必须是永久mediaID)
     8     
     9     private String author;//作者
    10     
    11     private String digest;//图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空
    12     
    13     private String content;//图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,且此处会去除JS
    14     
    15     private String url;//图文页的URL,或者,当获取的列表是图片素材列表时,该字段是图片的URL
    16     
    17     private int show_cover_pic;//是否显示封面,0为false,即不显示,1为true,即显示
    18     
    19     public String getTitle() {
    20         return title;
    21     }
    22     public void setTitle(String title) {
    23         this.title = title;
    24     }
    25     public String getThumb_media_id() {
    26         return thumb_media_id;
    27     }
    28     public void setThumb_media_id(String thumb_media_id) {
    29         this.thumb_media_id = thumb_media_id;
    30     }
    31     public String getAuthor() {
    32         return author;
    33     }
    34     public void setAuthor(String author) {
    35         this.author = author;
    36     }
    37     public String getDigest() {
    38         return digest;
    39     }
    40     public void setDigest(String digest) {
    41         this.digest = digest;
    42     }
    43     public String getContent() {
    44         return content;
    45     }
    46     public void setContent(String content) {
    47         this.content = content;
    48     }
    49     public String getUrl() {
    50         return url;
    51     }
    52     public void setUrl(String url) {
    53         this.url = url;
    54     }
    55     public int getShow_cover_pic() {
    56         return show_cover_pic;
    57     }
    58     public void setShow_cover_pic(int show_cover_pic) {
    59         this.show_cover_pic = show_cover_pic;
    60     }
    61     
    62 }

    获取素材列表调用接口所需要的参数实体类MaterialParam.java

     1 package com.shihe.shcoud.utils.pojo;
     2 /*获取素材列表调用接口所需要的参数实体类**/
     3 public class MaterialParam {
     4     
     5     private String type;//素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
     6     
     7     private int offset;//从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
     8     
     9     private int count;//返回素材的数量,取值在1到20之间
    10 
    11     public String getType() {
    12         return type;
    13     }
    14 
    15     public void setType(String type) {
    16         this.type = type;
    17     }
    18 
    19     public int getOffset() {
    20         return offset;
    21     }
    22 
    23     public void setOffset(int offset) {
    24         this.offset = offset;
    25     }
    26 
    27     public int getCount() {
    28         return count;
    29     }
    30 
    31     public void setCount(int count) {
    32         this.count = count;
    33     }
    34     
    35 }

    注意重写get和set方法。

    接下便是测试所写的方法是否能获取到素材列表信息了,这里我用的JUnit测试

    1 public class MaterialTest {
    2     
    3     @Test
    4     public void testGetMaterial() {
    5         Token token = CommonUtil.getToken(WeChatConfig.APP_ID,WeChatConfig.APP_SECRET);//获取接口访问凭证access_token
    6         List<Material> lists = CommonUtil.getMaterial(token.getAccessToken(),"news",0,10);//调用获取素材列表的方法
    7         System.out.println(lists.size());//输出
    8     }
    9 }

    这里我获取的是素材列表是图文消息,type类型也就是“news”图文消息,offset为0,也就是从第一个开始获取,count为10,获取素材的数量。

    这里我写的输出语句为存入list里面的素材数量。运行输出,正常输出结果。

    如果想看到输出的具体数据,在获取素材列表方法的for循环中我写了一个输出语句:System.out.println(json);这样运行就可以看出所需要获取到的素材列表内容了。

    如果是要获取到图片素材列表的,可以将getMaterial方法中的第10行定义图文素材类的集合替换为:List<MaterialImage> list = new ArrayList<MaterialImage>();

    然后将try catch里面的获取图文素材列表的方法给替换为相应的获取图片素材的方法,具体方法为:

     1        JSONArray jsonArray = jsonObject.getJSONArray("item");
     2         for (int i = 0; i < jsonArray.size(); i++) {
     3             JSONObject json = (JSONObject) jsonArray.get(i);
     4             MaterialImage image = new MaterialImage();
     5             image.setMedia_id(json.getString("media_id"));
     6             image.setName(json.getString("name"));
     7             try {
     8                 /**旧的image 没有url 需处理异常 新添加的有url*/
     9                 image.setUrl(json.getString("url"));
    10             } catch (Exception e) {
    11                 System.out.println("url 不存在异常");
    12             }
    13             list.add(image);

    其中用到的MaterialImage实体类方法为:

     1 /**素材图片实体类*/
     2 public class MaterialImage {
     3     
     4     //要获取的素材的media_id
     5     private String media_id;
     6     //文件名称
     7     private String name;
     8     //图片的URL
     9     private String url;
    10 
    11     public String getMedia_id() {
    12         return media_id;
    13     }
    14 
    15     public void setMedia_id(String media_id) {
    16         this.media_id = media_id;
    17     }
    18 
    19     public String getName() {
    20         return name;
    21     }
    22 
    23     public void setName(String name) {
    24         this.name = name;
    25     }
    26 
    27     public String getUrl() {
    28         return url;
    29     }
    30 
    31     public void setUrl(String url) {
    32         this.url = url;
    33     }
    34     
    35     
    36 }

     

    到处,所需要的方法写完了。自己内测还没有出现什么问题,本来测试的也不多。至于想把这些数据存入数据库等,自己写个数据表,写个批量插入即可。

    在此提供一下获取access_token的方法,我也是写在这个工具类中的:

     1 /**
     2      * 获取接口访问凭证
     3      * 
     4      * @param appid 凭证
     5      * @param appsecret 密钥
     6      * @return
     7      */
     8     public static Token getToken(String appid, String appsecret) {
     9         Token token = null;
    10         String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);//替换相应的参数
    11         // 发起GET请求获取凭证
    12         JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);//发送https请求
    13         if (null != jsonObject) {
    14             try {
    15                 token = new Token();
    16                 token.setAccessToken(jsonObject.getString("access_token"));
    17                 token.setExpiresIn(jsonObject.getInt("expires_in"));
    18             } catch (JSONException e) {
    19                 token = null;
    20                 // 获取token失败
    21                 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
    22             }
    23         }
    24         return token;
    25     }

    调用这个方法获取到的有两个值:access_token获取到的凭证和expires_in凭证有效时间,单位为秒。这个方法中所需要的参数就是你公众微信号上的appID和appsecret,对应填入即可。

    顺便给个接口凭证的实体类Token.javaJUnit测试方法:

     1 /**
     2  * 凭证
     3  * access_token
     4  * @author Admin
     5  *
     6  */
     7 public class Token {
     8     
     9     // 接口访问凭证
    10     private String accessToken;
    11     // 凭证有效期,单位:秒
    12     private int expiresIn;
    13     
    14     public String getAccessToken() {
    15         return accessToken;
    16     }
    17     public void setAccessToken(String accessToken) {
    18         this.accessToken = accessToken;
    19     }
    20     public int getExpiresIn() {
    21         return expiresIn;
    22     }
    23     public void setExpiresIn(int expiresIn) {
    24         this.expiresIn = expiresIn;
    25     }
    26 }

    JUnit测试的方法:

    1 @Test
    2     public void testGetToken2() {
    3         Token token = CommonUtil.getToken(WeChatConfig.APP_ID,WeChatConfig.APP_SECRET);//其中的WeChatConfig方法中有定义的自己微信公众号的appid和appsecret值 用到时直接调用
    4         System.out.println("access_token:"+token.getAccessToken());
    5         System.out.println("expires_in:"+token.getExpiresIn());
    6     }

    替换相应的appID和appsecret即可。

    上面即时获取的全部方法了,具体实现测试后在做后期修改,溜了。

     

    转载于:https://www.cnblogs.com/ka-bu-qi-nuo/p/9052387.html

    展开全文
  • 微信开发第七篇发送素材(图文)信息 2015年08月31日 16:00:29 主沉浮 阅读数:6979 https://blog.csdn.net/u010773333/article/details/48135043 最近产品经理要做每天推送图文信息的功能,哎,还要超链接传递...

    微信开发第七篇发送素材(图文)信息

    2015年08月31日 16:00:29 主沉浮 阅读数:6979

    https://blog.csdn.net/u010773333/article/details/48135043

    最近产品经理要做每天推送图文信息的功能,哎,还要超链接传递不同的参数,苦逼呀。。网上查了一些资料,下面讲解一下群发素材

    要群发素材,首先要先获得素材,素材都是以图片和文字的形式推送给用户的,所以要首先获得图片和文字

    微信的上传媒体接口:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE

    可以用来上传图片,上传成功返回:{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},其中media_id就是图片在微信服务器的标识。

    上传方法:

           /// <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);
            }

    第二步:拼接图文消息素材Json字符串,其中msg就是上述的微信服务器传回来的媒体ID

           /// <summary> 
            /// 拼接图文消息素材Json字符串 
            /// </summary> 
            public static string GetArticlesJsonStr(string access_token,string msg)
            {
                StringBuilder sbArticlesJson = new StringBuilder();

                 sbArticlesJson.Append("{\"articles\":[");
                    //string media_id = Tools.GetJsonValue(msg, "media_id");
                   // string media_id = (msg,"media_id");
                    sbArticlesJson.Append("{");
                    // sbArticlesJson.Append();
                    sbArticlesJson.Append("\"thumb_media_id\":\"" + msg + "\",");
                    sbArticlesJson.Append("\"author\":\"" + "王华涛" + "\",");
                    sbArticlesJson.Append("\"title\":\"" + "作业已经完成" + "\",");
                    sbArticlesJson.Append("\"content_source_url\":\"" + "http://。。。。" + "\",");
                    sbArticlesJson.Append("\"content\":\"" + "作业信息" + "\",");
                    sbArticlesJson.Append("\"digest\":\"" +"您孩子的作业已经完成" + "\",");
                    sbArticlesJson.Append("\"show_cover_pic\":\"1\"}");
                    sbArticlesJson.Append("]}");

                return sbArticlesJson.ToString();
            } 

    第三步:上传图文消息素材,其中postData就是拼接图文消息素材Json字符串,调用微信接口上传之后获得media_id 

            /// <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);
            }

    第四步:图文消息json,添加发送用户openid

          /// <summary> 
            /// 图文消息json 
            /// </summary> 
            public static string CreateNewsJson(string media_id, List<string> openids)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("{\"touser\":[\"");

                foreach(string  openid in openids)     

                {

                     sb.Append(openid);
                    sb.Append("\",\"");

                }
                sb.Append("\"],");
                sb.Append("\"msgtype\":\"mpnews\",");
                sb.Append("\"mpnews\":{\"media_id\":\"" + media_id + "\"}");
                sb.Append("}");
                return sb.ToString();
            }
    第五步:调用微信发送素材接口,根据OpenID列表群发素材信息

            /// <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);
            } 
     

    展开全文
  • 最近在做关于微信公众号接口的问题,发现上传永久素材的地方有些小问题。 1.临时素材和永久素材没有关系,在微信服务器可以保存三天。新增的临时素材只能通过media_id(临时素材)获取。 2.新增图文素材以外的素材...

      最近在做关于微信公众号接口的问题,发现上传永久素材的地方有些小问题。

    1.临时素材和永久素材没有关系,在微信服务器可以保存三天。新增的临时素材只能通过media_id(临时素材)获取。

    2.新增图文素材以外的素材,需要使用‘新增其他类型永久素材’接口,其中文档写的地址为

      http请求方式: POST,需使用https https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN

      在测试的过程中发现,少了type属性。我之前一直用json对象传值进去,所以总是出现各种错误。

      通过这个接口就可以获得到media_id(永久素材)。

    3.上传需要使用multipart/form-data方式。

    下面是代码,在网上搜了一些高手的方法,稍微进行了一下组合,亲测可用

            /// <summary>
            /// 新增永久素材
            /// </summary>
            /// <param name="form"></param>
            /// <returns></returns>
            [HttpPost]
            public string UploadLong(FormCollection form)
            {
    
                if (Request.Files.Count == 0)
                {
                    //Request.Files.Count 文件数为0上传不成功
                    return "文件数为0上传不成功";
                }
                var file = Request.Files[0];
                if (file.ContentLength == 0)
                {
                    //文件大小(以字节为单位)为0时,做一些操作
                    return "文件大小(以字节为单位)为0";
                }
                else
                {
                    //文件大小不为0
                    HttpPostedFileBase files = Request.Files[0];
                    string type = "image";
                    string url = string.Format("http://api.weixin.qq.com/cgi-bin/material/add_material?access_token={0}&type={1}", token, type.ToString());
                    string path = "C://Users//xjh//Desktop//img//" + files.FileName;
                    //服务器上的UpLoadFile文件夹必须有读写权限      
                    files.SaveAs(path);
                    string filename = System.Web.HttpContext.Current.Server.MapPath("/image/" + files.FileName);
                    //返回url
                    //var geturl = HttpUploadFile(string.Format("https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={0}", token), file.FileName);
                    string json = HttpUploadFile(url, filename);
                    JObject jb = (JObject)JsonConvert.DeserializeObject(json);
                    //todo
                    return json;
                }
            }

    以下为post方法

            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=\"media\";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;
            }

     

    转载于:https://www.cnblogs.com/tearfc/p/5466127.html

    展开全文
  • 本文是 微信公众号开发者模式介绍及接入 的后续,如没看过前文的话,可能看本文会有些懵逼。本文主要介绍微信公众平台的素材、消息管理接口的开发。由于个人的订阅号是没有大多数接口的权限的,所以我们需要使用微信...

    开始

    本文是 微信公众号开发者模式介绍及接入 的后续,如没看过前文的话,可能看本文会有些懵逼。本文主要介绍微信公众平台的素材、消息管理接口的开发。由于个人的订阅号是没有大多数接口的权限的,所以我们需要使用微信官方提供的测试号来进行开发。测试号的申请可参考下文:


    图文消息

    本小节我们来开发回复图文消息的功能,官方文档地址如下:

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543

    回复图文消息所需传递的参数如下:
    微信公众号开发-素材/消息管理接口

    注:多图文消息不会显示Description参数的信息

    官方的图文消息示例数据结构如下:

    <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[url]]>
                </Url>
            </item>
            <item>
                <Title>
                    <![CDATA[title]]>
                </Title>
                <Description>
                    <![CDATA[description]]>
                </Description>
                <PicUrl>
                    <![CDATA[picurl]]>
                </PicUrl>
                <Url>
                    <![CDATA[url]]>
                </Url>
            </item>
        </Articles>
    </xml>

    图文消息都在Articles标签内,而每个item标签都包含一条图文消息,有多少个item标签就代表有多少条图文消息。

    在开发回复图文消息的时候,我们需要使用到一张图片来作为图文消息的封面,找一个图片文件放在工程的resources/static目录下即可,并确保能够在外网上访问:
    微信公众号开发-素材/消息管理接口

    看完了官方的示例数据及文档,那么我们就来开发一下图文消息的回复吧。首先是创建一个基类,封装通用的字段,代码如下:

    package org.zero01.weixin.mqdemo.vo;
    
    import com.thoughtworks.xstream.annotations.XStreamAlias;
    import lombok.Getter;
    import lombok.Setter;
    
    /**
     * @program: mq-demo
     * @description: 图文消息基类
     * @author: 01
     * @create: 2018-07-02 20:24
     **/
    @Getter
    @Setter
    public class BaseMassage {
    
        /**
         * 接收方账号
         */
        @XStreamAlias("ToUserName")
        private String toUserName;
    
        /**
         * 发送方账号
         */
        @XStreamAlias("FromUserName")
        private String fromUserName;
    
        /**
         * 消息创建时间 (整型)
         */
        @XStreamAlias("CreateTime")
        private long createTime;
    
        /**
         * 消息类型
         */
        @XStreamAlias("MsgType")
        private String msgType;
    }

    然后是具体的封装每条图文消息字段的对象,代码如下:

    package org.zero01.weixin.mqdemo.vo;
    
    import com.thoughtworks.xstream.annotations.XStreamAlias;
    import lombok.Getter;
    import lombok.Setter;
    
    /**
     * @program: mq-demo
     * @description: 图文消息对象
     * @author: 01
     * @create: 2018-07-02 20:19
     **/
    @Getter
    @Setter
    public class NewsItem{
        @XStreamAlias("Title")
        private String title;
    
        @XStreamAlias("Description")
        private String description;
    
        @XStreamAlias("PicUrl")
        private String picUrl;
    
        @XStreamAlias("Url")
        private String url;
    }

    接着是包含每条图文消息的容器对象,代码如下:

    package org.zero01.weixin.mqdemo.vo;
    
    import com.thoughtworks.xstream.annotations.XStreamAlias;
    import lombok.Getter;
    import lombok.Setter;
    
    import java.util.List;
    
    /**
     * @program: mq-demo
     * @description: 图文消息容器对象
     * @author: 01
     * @create: 2018-07-02 20:29
     **/
    @Getter
    @Setter
    public class NewsMessage extends BaseMassage{
        @XStreamAlias("ArticleCount")
        private int articleCount;
    
        @XStreamAlias("Articles")
        private List<NewsItem> articles;
    }

    将图文消息结构都封装成一个个的类后,就是需要组装图文消息以及将组装好的图文消息转换成xml格式的数据,发送给微信服务器了。所以我们需要在MessageUtil类中,新增如下两个方法:

    /**
     * 图文消息转换为xml
     *
     * @param newsMessage
     * @return
     */
    public static String newsMessageToXml(NewsMessage newsMessage) {
        XStream xStream = new XStream();
        xStream.processAnnotations(new Class[]{NewsItem.class, NewsMessage.class});
        xStream.alias("xml", newsMessage.getClass());
        xStream.alias("item", NewsItem.class);
    
        return xStream.toXML(newsMessage);
    }
    
    /**
     * 组装图文消息
     *
     * @param toUserName
     * @param fromUserName
     * @return
     */
    public static String initNewsMessage(String toUserName, String fromUserName) {
        List<NewsItem> newsItemList = new ArrayList<>();
        NewsMessage newsMessage = new NewsMessage();
    
        NewsItem newsItem = new NewsItem();
        newsItem.setTitle("图文消息");
        newsItem.setDescription("这是一个图文消息");
        newsItem.setPicUrl("http://zero.mynatapp.cc/code.jpg");
        newsItem.setUrl("www.baidu.com");
        newsItemList.add(newsItem);
    
        newsMessage.setToUserName(fromUserName);
        newsMessage.setFromUserName(toUserName);
        newsMessage.setCreateTime(System.currentTimeMillis());
        newsMessage.setMsgType(MessageTypeEnum.MSG_NEWS.getMsgType());
        newsMessage.setArticles(newsItemList);
        newsMessage.setArticleCount(newsItemList.size());
    
        return newsMessageToXml(newsMessage);
    }

    最后修改WeChatMqController中的text方法,增加一条判断,判断当用户输入数字1时,则回复图文消息。代码如下:

    @PostMapping("/common")
    public String text(@RequestBody String xmlStr) {
        // 将xml格式的数据,转换为 AllMessage 对象
        AllMessage allMessage = MessageUtil.xmlToAllMessage(xmlStr);
    
        // 是否是文本消息类型
        if (allMessage.getMsgType().equals(MessageTypeEnum.MSG_TEXT.getMsgType())) {
            // 用户输入数字1时,回复图文消息
            if ("1".equals(allMessage.getContent())) {
                return MessageUtil.initNewsMessage(allMessage.getToUserName(), allMessage.getFromUserName());
            }
            // 自动回复用户所发送的文本消息
            return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_PREFIX.getContent() + allMessage.getContent());
        }
        // 是否是事件推送类型
        else if (allMessage.getMsgType().equals(MessageTypeEnum.MSG_EVENT.getMsgType())) {
            // 是否为订阅事件
            if (EventType.EVENT_SUBSCRIBE.getEventType().equals(allMessage.getEvent())) {
                // 自动回复欢迎语
                return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_SUBSCRIBE.getContent());
            }
        } else {
            // 暂不支持文本以外的消息回复
            return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_NONSUPPORT.getContent());
        }
        return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_NONSUPPORT.getContent());
    }

    完成以上代码的编写后,启动SpringBoot,打开微信公众号,测试结果如下:
    微信公众号开发-素材/消息管理接口


    access_token的获取

    本小节我们来看看如何获取access_token,官方文档地址如下:

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

    access_token是什么?官方的定义如下:

    access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

    调用接口获取access_token需要传递的参数说明如下:
    微信公众号开发-素材/消息管理接口

    获取access_token成功后,接口所返回的参数说明如下:
    微信公众号开发-素材/消息管理接口

    从文档中我们可以看到,调用接口获取access_token时需要传递appid和secret,appid和secret可以在公众号的基本配置页面中获取,如下:
    微信公众号开发-素材/消息管理接口

    然后我们还需要安装提示,设置一下白名单的ip,即你机器的ip,不然是无法调用接口获取access_token的,如下:
    微信公众号开发-素材/消息管理接口

    将appid、secret以及获取access_token的接口url,配置到SpringBoot的配置文件中,如下:

    wechat:
      mpAppid: wx8ed1xxxxxx9513dd
      mpAppSecret: 0c1b5b7ea5xxxxxxxxx14cb5b61258
      accessTokenUrl: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

    在工程中新建一个config包,在该包下新建一个 WeXinConfig 配置类,用于加载配置文件中所配置的appid和secret:

    package org.zero01.weixin.mqdemo.config;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @program: mq-demo
     * @description: 微信公众号配置类
     * @author: 01
     * @create: 2018-07-03 20:50
     **/
    @Data
    @Configuration
    @ConfigurationProperties(prefix = "wechat")
    public class WeXinConfig {
        private String mpAppid;
        private String mpAppSecret;
        private String accessTokenUrl;
    }

    因为我们需要序列化json数据以及发送http请求给微信服务器,所以需要使用到一些工具包,在maven的pom.xml文件中,加入如下依赖:

    <!-- https://mvnrepository.com/artifact/org.json/json -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20160810</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.5</version>
    </dependency>

    在util包下新建一个 WeiXinUtil 工具类,在该类中封装get、post请求方法,以及获取access_token的方法。代码如下:

    package org.zero01.weixin.mqdemo.util;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.util.EntityUtils;
    import org.json.JSONObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.zero01.weixin.mqdemo.config.WeXinConfig;
    import org.zero01.weixin.mqdemo.vo.AccessToken;
    
    import java.io.IOException;
    
    /**
     * @program: mq-demo
     * @description: 
     * @author: 01
     * @create: 2018-07-03 21:04
     **/
    @Component
    public class WeiXinUtil {
    
        private static WeXinConfig wxConfig;
    
        public WeXinConfig getWeXinConfig() {
            return wxConfig;
        }
    
        @Autowired
        public void setWeXinConfig(WeXinConfig wxConfig) {
            WeiXinUtil.wxConfig = wxConfig;
        }
    
        /**
         * get请求
         *
         * @param url
         * @return
         */
        public static JSONObject doGet(String url) throws IOException {
            CloseableHttpClient client = HttpClientBuilder.create().build();
            HttpGet httpGet = new HttpGet(url);
    
            HttpResponse response = client.execute(httpGet);
            String result = EntityUtils.toString(response.getEntity(), "utf-8");
    
            return new JSONObject(result);
        }
    
        /**
         * post请求
         *
         * @param url
         * @param outStr
         * @return
         */
        public static JSONObject doPost(String url, String outStr) throws IOException {
            CloseableHttpClient client = HttpClientBuilder.create().build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new StringEntity(outStr, "utf-8"));
    
            HttpResponse response = client.execute(httpPost);
            String result = EntityUtils.toString(response.getEntity(), "utf-8");
    
            return new JSONObject(result);
        }
    
        /**
         * 获取access_token
         *
         * @return
         * @throws IOException
         */
        public static AccessToken getAccessToken() throws IOException {
            AccessToken token = new AccessToken();
            // 替换appid和secret
            String url = wxConfig.getAccessTokenUrl()
                    .replace("APPID", wxConfig.getMpAppid())
                    .replace("APPSECRET", wxConfig.getMpAppSecret());
    
            JSONObject jsonObject = doGet(url);
            token.setToken(jsonObject.getString("access_token"));
            token.setExpiresIn(jsonObject.getInt("expires_in"));
    
            return token;
        }
    }

    完成以上代码的编写后,新建一个测试类,测试一下是否能正常获取到access_token。测试代码如下:

    package org.zero01.weixin.mqdemo.util;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.zero01.weixin.mqdemo.vo.AccessToken;
    
    import java.io.IOException;
    
    import static org.junit.Assert.*;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class WeiXinUtilTest {
    
        @Test
        public void getAccessToken() throws IOException {
            AccessToken accessToken = WeiXinUtil.getAccessToken();
            System.out.println("access_token: " + accessToken.getToken());
            System.out.println("有效时间: " + accessToken.getExpiresIn());
        }
    }

    运行以上测试用例后,控制台输出如下:

    access_token: 11_AMxhxO9soXndEc6XI-0hG0CWQ_oVQjaiPol6P2eMDLrSYpIrbiNMjHEDFwoOiKwG-ckgwPTHCiWypzK_reZohT7H5UdEYUmdlU_qq-oGQefv9q9A4mEkFV5WyiEFK5q5SsvsLR5QIKcjf1BhLDEfAIAAST
    有效时间: 7200

    从测试结果中,可以看到,成功获取到了access_token,并且这个access_token的有效期是7200秒,也就是两个小时,和官方文档描述的一致。

    一般在实际的项目开发中,我们都会把这个access_token缓存起来,缓存到本地或者nosql数据库中,然后每隔1.5个小时或2个小时的时候,就重新获取一次access_token,刷新缓存。这样做是为了避免在每个逻辑点都去重新获取access_token,因为这样会导致服务的不稳定,而且微信也规定了获取access_token的接口每天只能调用2000次,如果每个逻辑点都去重新获取access_token的话,不仅会导致服务不稳定,还容易把调用次数给花完。如下:
    微信公众号开发-素材/消息管理接口


    图片消息回复

    本小节我们来看看如何进行图片消息的回复,官方文档地址如下:

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543

    回复图片消息所需传递的参数如下:
    微信公众号开发-素材/消息管理接口

    官方的图文消息示例数据结构如下:

    <xml>
        <ToUserName>
            <![CDATA[toUser]]>
        </ToUserName>
        <FromUserName>
            <![CDATA[fromUser]]>
        </FromUserName>
        <CreateTime>12345678</CreateTime>
        <MsgType>
            <![CDATA[image]]>
        </MsgType>
        <Image>
            <MediaId>
                <![CDATA[media_id]]>
            </MediaId>
        </Image>
    </xml>

    从所需传递的参数列表中可以看到,回复图片消息时需要传递一个MediaId,这是通过素材管理中的接口上传多媒体文件,得到的id。所以在开发回复图片消息的接口前,我们还需要开发一个上传多媒体文件的接口,以此来获得MediaId。关于素材管理接口的官方文档地址如下:

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738726

    新增临时素材接口调用说明如下:
    微信公众号开发-素材/消息管理接口

    上传素材成功后,返回的参数如下:
    微信公众号开发-素材/消息管理接口

    有一点要说明的是,个人的订阅号是没有素材管理接口的权限的,所以我们需要将之前配置的appid和AppSecret配置为测试号的,不然接口会调用失败,如果是已认证的服务号就可以直接使用。

    由于需要上传图片素材才能发送图片消息,所以首先需要在 WexinUtil 中,新增一个 upload 方法,用于上传临时图片素材并返回素材的media_id。

    但是在写代码前,需要先将上传临时素材的接口url地址配置到SpringBoot的配置文件中,如下:

    wechat:
      ...
      uploadUrl: https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE

    然后在配置类里加上这个配置的字段,如下:

    ...
    public class WeXinConfig {
        ...
        private String uploadUrl;
    }

    upload 方法代码如下:

    /**
     * 上传临时素材
     *
     * @param filePath    需要上传的文件所在路径
     * @param accessToken access_token
     * @param type        素材类型
     * @return media_id
     * @throws IOException
     */
    public static String upload(String filePath, String accessToken, String type, String key) throws IOException {
        File file = new File(filePath);
        if (!(file.exists() || file.isFile())) {
            throw new IOException("文件不存在");
        }
    
        String url = wxConfig.getUploadUrl()
                .replace("ACCESS_TOKEN", accessToken)
                .replace("TYPE", type);
    
        URL urlObj = new URL(url);
        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
    
        // 设置属性
        connection.setRequestMethod("POST");
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);
    
        // 设置头信息
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Charset", "UTF-8");
    
        // 设置边界
        String boundary = "----------" + System.currentTimeMillis();
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
    
        StringBuilder sb = new StringBuilder();
        sb.append("--").append(boundary).append("\r\n")
                .append("Content-Disposition;form-data;name=\"file\";filename=\"")
                .append(file.getName())
                .append("\"\r\n")
                .append("Content-Type:application/octet-stream\r\n\r\n");
    
        byte[] head = sb.toString().getBytes("UTF-8");
    
        // 获得输出流
        OutputStream output = new DataOutputStream(connection.getOutputStream());
        // 输出表头
        output.write(head);
    
        // 文件正文部分
        // 把文件以流文件的方式,推入到url中
        DataInputStream input = new DataInputStream(new FileInputStream(file));
        int bytes = 0;
        byte[] bufferOutput = new byte[1024];
        while ((bytes = input.read(bufferOutput)) != -1) {
            output.write(bufferOutput, 0, bytes);
        }
        input.close();
    
        // 结尾部分,定义最后数据分割线
        byte[] foot = ("\r\n--" + boundary + "--\r\n").getBytes("utf-8");
        output.write(foot);
        output.flush();
        output.close();
    
        StringBuilder buffer = new StringBuilder();
        String result = null;
    
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
            String line = null;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
    
            result = buffer.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        JSONObject jsonObject = new JSONObject(result);
        log.info("response data: {}", jsonObject);
    
        return jsonObject.getString(key);
    }

    在测试类中新增一个测试方法,测试代码如下:

    @Test
    public void upload() throws IOException {
        String filePath = "Z:/v2-9b17df91629f842edd472d7cfcaa9c4b_hd.jpg";
        AccessToken accessToken = WeiXinUtil.getAccessToken();
        String mediaId = WeiXinUtil.upload(filePath, accessToken.getToken(), "image");
    
        System.out.println(mediaId);
    }

    控制台输出结果如下:

    mediaId: 5_PCrofX1_KIpSfWzJE-tu7AxQjxw6zlQ44oBuUkM_PZ6FiPeDY0a7vcWU2zdap9

    获取到media_id后,就可以开始开发回复图片消息功能了,首先根据官方给出的数据结构,封装好各个实体类。Image类代码如下:

    package org.zero01.weixin.mqdemo.vo;
    
    import com.thoughtworks.xstream.annotations.XStreamAlias;
    import lombok.Data;
    
    @Data
    public class Image {
        @XStreamAlias("MediaId")
        private String mediaId;
    }

    ImageMessage类代码如下:

    package org.zero01.weixin.mqdemo.vo;
    
    import com.thoughtworks.xstream.annotations.XStreamAlias;
    import lombok.Data;
    
    @Data
    public class ImageMessage extends BaseMassage {
        @XStreamAlias("Image")
        private Image image;
    }

    然后在MessageUtil中新增如下两个方法:

    /**
     * 将图片消息转换为xml
     *
     * @param imageMessage
     * @return
     */
    public static String imageMessageToXml(ImageMessage imageMessage) {
        XStream xStream = new XStream();
        xStream.processAnnotations(new Class[]{ImageMessage.class, Image.class});
        xStream.alias("xml", imageMessage.getClass());
    
        return xStream.toXML(imageMessage);
    }
    
    /**
     * 组装图片消息对象
     *
     * @param toUserName
     * @param fromUserName
     * @return
     */
    public static String initImageMessage(String toUserName, String fromUserName) {
        Image image = new Image();
        image.setMediaId("5_PCrofX1_KIpSfWzJE-tu7AxQjxw6zlQ44oBuUkM_PZ6FiPeDY0a7vcWU2zdap9");
        ImageMessage imageMessage = new ImageMessage();
        imageMessage.setFromUserName(toUserName);
        imageMessage.setToUserName(fromUserName);
        imageMessage.setMsgType(MessageTypeEnum.MSG_IMAGE.getMsgType());
        imageMessage.setCreateTime(System.currentTimeMillis());
        imageMessage.setImage(image);
    
        return imageMessageToXml(imageMessage);
    }

    最后修改WeChatMqController中的text方法,增加一条判断,判断当用户输入数字2时,则回复图片消息。代码如下:

    ...
    
        if ("1".equals(allMessage.getContent())) {
            return MessageUtil.initNewsMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        } else if ("2".equals(allMessage.getContent())) {
            return MessageUtil.initImageMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        }
    
    ...

    完成以上代码的编写后,重启SpringBoot,打开微信公众号,测试结果如下:
    微信公众号开发-素材/消息管理接口


    音乐消息回复

    在上一小节中,我们介绍了如何开发回复图片消息的功能,而其他类似的消息回复都是差不多的,这里就不一一去赘述了。本小节我们来看看如何进行音乐消息回复的开发,官方文档地址如下:

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543

    回复音乐消息所需传递的参数如下:
    微信公众号开发-素材/消息管理接口

    官方的图文消息示例数据结构如下:

    <xml>
        <ToUserName>
            <![CDATA[toUser]]>
        </ToUserName>
        <FromUserName>
            <![CDATA[fromUser]]>
        </FromUserName>
        <CreateTime>12345678</CreateTime>
        <MsgType>
            <![CDATA[music]]>
        </MsgType>
        <Music>
            <Title>
                <![CDATA[TITLE]]>
            </Title>
            <Description>
                <![CDATA[DESCRIPTION]]>
            </Description>
            <MusicUrl>
                <![CDATA[MUSIC_Url]]>
            </MusicUrl>
            <HQMusicUrl>
                <![CDATA[HQ_MUSIC_Url]]>
            </HQMusicUrl>
            <ThumbMediaId>
                <![CDATA[media_id]]>
            </ThumbMediaId>
        </Music>
    </xml>

    开发音乐消息回复,我们需要一个音乐文件,找一个mp3文件放在工程的resources/static目录下即可,并确保能够在外网上访问:
    微信公众号开发-素材/消息管理接口

    根据官方给出的数据结构,封装好各个实体类。Music 实体类代码如下:

    package org.zero01.weixin.mqdemo.vo;
    
    import com.thoughtworks.xstream.annotations.XStreamAlias;
    import lombok.Data;
    
    @Data
    public class Music {
    
        @XStreamAlias("Title")
        private String title;
    
        @XStreamAlias("Description")
        private String description;
    
        @XStreamAlias("MusicUrl")
        private String musicUrl;
    
        @XStreamAlias("HQMusicUrl")
        private String hQMusicUrl;
    
        @XStreamAlias("ThumbMediaId")
        private String thumbMediaId;
    }

    MusicMessage 实体类代码如下:

    package org.zero01.weixin.mqdemo.vo;
    
    import com.thoughtworks.xstream.annotations.XStreamAlias;
    import lombok.Data;
    
    @Data
    public class MusicMessage extends BaseMassage {
    
        @XStreamAlias("Music")
        private Music music;
    }

    由于音乐消息需要传递一个ThumbMediaId,也就是缩略图的媒体id。所以我们需要修改之前的测试代码,以此获取thumb_media_id,如下:

    @Test
    public void upload() throws IOException {
        String filePath = "Z:/v2-9b17df91629f842edd472d7cfcaa9c4b_hd.jpg";
        AccessToken accessToken = WeiXinUtil.getAccessToken();
        String thumbMediaId = WeiXinUtil.upload(filePath, accessToken.getToken(), "thumb","thumb_media_id");
    
        System.out.println("thumb_media_id: " + thumbMediaId);
    }

    执行以上测试方法,控制台输出的结果如下:

    thumb_media_id: Iu9puUGeFcS8HWyBGepJfeGoLDV_sWg8vJTeG-akMhcSGrqFjvoimMhCfjWw8F53

    复制好thumb_media_id,然后在MessageUtil中新增如下两个方法:

    /**
     * 将音乐消息转换为xml
     *
     * @param musicMessage
     * @return
     */
    public static String musicMessageToXml(MusicMessage musicMessage) {
        XStream xStream = new XStream();
        xStream.processAnnotations(new Class[]{MusicMessage.class, Music.class});
        xStream.alias("xml", musicMessage.getClass());
    
        return xStream.toXML(musicMessage);
    }
    
    /**
     * 组装音乐消息对象
     *
     * @param toUserName
     * @param fromUserName
     * @return
     */
    public static String initMusicMessage(String toUserName, String fromUserName) {
        Music music = new Music();
        music.setTitle("音乐消息");
        music.setDescription("这是一个音乐消息");
        music.setThumbMediaId("Iu9puUGeFcS8HWyBGepJfeGoLDV_sWg8vJTeG-akMhcSGrqFjvoimMhCfjWw8F53");
        music.setMusicUrl("http://zero.mynatapp.cc/Unravel.mp3");
        music.setHQMusicUrl("http://zero.mynatapp.cc/Unravel.mp3");
    
        MusicMessage musicMessage = new MusicMessage();
        musicMessage.setFromUserName(toUserName);
        musicMessage.setToUserName(fromUserName);
        musicMessage.setMsgType(MessageTypeEnum.MSG_MUSIC.getMsgType());
        musicMessage.setCreateTime(System.currentTimeMillis());
        musicMessage.setMusic(music);
    
        return musicMessageToXml(musicMessage);
    }

    最后修改WeChatMqController中的text方法,增加一条判断,判断当用户输入数字3时,则回复音乐消息。代码如下:

    ...
    
        if ("1".equals(allMessage.getContent())) {
            return MessageUtil.initNewsMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        } else if ("2".equals(allMessage.getContent())) {
            return MessageUtil.initImageMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        } else if ("3".equals(allMessage.getContent())) {
            return MessageUtil.initMusicMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        }
    
    ...

    完成以上代码的编写后,重启SpringBoot,打开微信测试公众号进行测试,测试结果如下:
    微信公众号开发-素材/消息管理接口

    点击音乐消息,打开后效果如下:
    微信公众号开发-素材/消息管理接口

    注:我这用的是pc端的微信,是可以正常播放的,但实际手机端很有可能无法播放,这也是微信的一个小坑

    转载于:https://blog.51cto.com/zero01/2136341

    展开全文
  • 前台原因就是发生在小程序中,最好的办法就是真机调试(手机预览和开发者工具中的运行效果总会发神经,并不是最可靠的)。在真机调试中打印出上传的文件或者图片在前台读取后的临时地址路径,观看路径有无问题。 2....
  • 要实现公众号编辑模式应用,先要开启编辑模式 微信公众平台后台管理提供了2种模式:编辑...基本配置,如图,如果未同意成为开发者,管理后台为编辑模式。 开启编辑模式后,我们进一步开发微信公众号! 两种...
  • 关于微信公众号中的订阅号和服务的区别这里不多加讨论,网上有很多资源可以搜到,这里直接进入正题,如果是个人开发者,这里建议使用测试号进行开发学习,测试号的权限要比个人订阅号要多的多,而本篇博客也是基于...
  • 随着移动互联网热浪的来临,微信服务号日益火热,不管是具有深厚开发功底的工程师,还是对编程完全不了解的微信爱好者,都盼望能充分的利益微信的强大功能。 本教程通过由浅入深的实例带领大家进入微信服务号的神奇...
  • pc端微信扫码支付

    2017-10-09 17:00:03
    首先需要在微信公众平台(注意不是微信开放平台)注册一个账号,并开通微信认证,微信认证一次需要300块(太tm的贵了),并且需要提交各种资料。 审核过后, 进入 开发-》...微信扫码支付模式有两种,第一种需要配置很
  • 概述最近应公司需求,对微信文章留言功能进行开发,然而由于微信文档描述贼简介,所以遇坑不断,特在此整理一下以便各位少走弯路。1. 留言功能开通首先,公众号需要具备可以进行留言的资格,如果你的公众号开通了...
  • 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版。为了满足第三方平台开发者的需求,在保留对openID预览能力的同时,增加了对指定微信号发送预览的能力,但该能力每日调用次数有限制(100次)...
  • 以图中的效果为例,我们可以进入开发者模式,选中这个区域,下面的代码区域会自动跳转到对应的代码区域,如图所示: 3. 接下来,我们选中这部分代码,点击右键,选择"Copy outerHTML",那么这部分代码会被复制下来...
  • 要实现公众号编辑模式应用,先要开启编辑模式 微信公众平台后台管理提供了2种模式:编辑...基本配置,如图,如果未同意成为开发者,管理后台为编辑模式。 开启编辑模式后,我们进一步开发微信公众号! 两种...
  • 微信开发学习总结

    2016-07-11 12:52:18
    微信开发项目学习总结
  • 微信小游戏的基础技术限制(egret引擎) 不允许操作 DOM、BOM、如果必须改成小游戏相应的 API 调用方式,目前引擎会自动引入weapp-adapter.js 文件做兼容处理。 不允许动态执行代码的能力,eval、setTimeout 和 ...
  • 为了帮助开发者简单和高效地开发和调试微信小程序,我们在原有的公众号网页调试工具的基础上,推出了全新的微信开发者工具,集成了公众号网页调试和小程序调试两种开发模式。 二、界面: 1、启动页 【1】登录页 在...
  • 作者:杨广辉 一、微信公众号简介 1、微信公众号介绍 微信公众号是开发者或商家在微信公众平台上申请的应用账号,...在这里可以通过微信渠道将品牌推广给上亿的微信用户,减少宣传成本,提高品牌知名度,打造更具影响力
  • 摘要:本文说明了在腾讯云服务器上通过“微信小程序专用解决方案”搭建、部署后端服务器及基础服务的过程。
1 2 3 4 5 ... 20
收藏数 893
精华内容 357
关键字:

微信开发者模式下添加素材