Skip to content
liangjiezhu edited this page Jan 20, 2016 · 2 revisions

Welcome to the WTF wiki! Wechat Framework开发者指南

1 总览

1.1 关于Wechat Framework

微信公众平台是运营者通过公众号为微信用户提供资讯和服务的平台,而公众平台开发接口则是提供服务的基础,开发者在公众平台网站中创建公众号、获取接口权限后,可以通过公众平台开发接口来开发功能强大的公众号。

Wechar Framework(微信开发框架,以下简称WTF)能帮助开发者快速搭建微信公众号开发环境,目前推出的WTF 1.0版实现了接口调用凭据获取、全部消息和事件的接收及回复、帐号管理等最基础也是最重要的功能。开发者在自己的微信公众号开发项目中引入本框架后,仅需简单的几步配置即可获得消息接收、解析、回复等功能,同时还有菜单创建,二维码请求等功能供开发者调用。

WTF使得开发者能够集中精力关注自身业务能力的开发,省去对Http、Xml、Json等大量基础能力模块的理解和构建,节省大量人力和时间。引入WTF使得微信公众号开发变成一件快速而简单的工作,尤其适合个人公众号,以及非软件研发专业公司的营销公众号的快速开发。

1.2 WTF快速入门

只需简单的四步操作,即可将WTF引入到自己的微信公众号项目中,搭建起一个具备菜单功能、消息接收和发送、以及更高级和复杂能力的微信公众号。

  1.     第一步:将WTF的4个jar包拷贝到项目的lib目录下,Web项目是在“WebContent\WEB-INF\lib”目录下,在eclipse中可以直接选中lib目录按Ctrl+C拷贝。以下是4个jar包的文件名和说明,以及下载地址:
    

halo-utils-1.0.jar

通用工具类,提供Http协议支持、Json解析和打包等功能。

halo-wechat-core-abilities-1.0.jar

微信公众平台接口的核心能力,消息接收和发送、接口调用凭据获取等。

halo-wechat-mvc-framework-1.0.jar

WTF使用了spring的mvc框架,使开发者无需编码或配置即可自动处理微信公众平台的Http请求。

halo-wechat-utils-1.0.jar

WTF框架工具类,如解析和生成XML文件的工具类等。

WTF下载:http://115.159.67.204/Tutorial/Download/wtf-1.0.rar

开源项目地址:https://github.com/junior9919/WTF

  1.     第二步:在项目的web.xml文件中增加以下配置:
    
     <param-name>contextConfigLocation</param-name>

     <param-value>classpath:com/halo/wechat/config/applicationContext-wechat.xml</param-value>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     <servlet-name>mvcFramework</servlet-name>

     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
               <param-name>contextConfigLocation</param-name>

               <param-value>classpath:com/halo/wechat/config/applicationContext-servlet.xml</param-value>

     </init-param>

     <load-on-startup>1</load-on-startup>
     <servlet-name>mvcFramework</servlet-name>

     <url-pattern>*.do</url-pattern>

熟悉Spring框架的开发者对以上的配置并不陌生,这实际上是在配置Spring的监听器和MVC框架的DispatcherServlet,只不过指明了要加载WTF的com/halo/wechat/config/applicationContext-wechat.xml和com/halo/wechat/config/applicationContext-servlet.xml这两个上下文(Context)配置文件(见红色字体标明部分)。这两个配置文件已经包含在WTF的jar包里。

开发者也可以同时加载自己的上下文(Context)配置文件,只需将红色字体标明部分改为以下形式:

self_aplicationContext.xml,classpath:com/halo/wechat/config/applicationContext-wechat.xml

self_aplicationContext_servlet.xml,classpath:com/halo/wechat/config/applicationContext-servlet.xml

例子中假设self_aplicationContext.xml和self_aplicationContext_servlet.xml是开发者自己的上下文配置,多个配置文件之间用“,”(半角逗号)隔开,当然,实际开发时你还需要在配置文件名前加上相对或绝对路径。

  1.     第三步:在项目的classpath目录下加入两个配置文件“log4j2.xml”和“wechat.properties”:
    

“log4j2.xml”是log4j(日志记录工具)的配置文件,内容不需要修改。

“wechat.properties”中需要配置开发者自己的微信公众号的app_id、app_secret和token,开发者在微信公众平台上可以找到这三个参数的配置。

以上两个文件在wtf-1.0.rar中都有。

  1.     第四步:实现WTF框架中的com.halo.wechat.mvc.commands.Command接口,开发者在这个实现类中编写消息和事件处理的代码,如下例子:
    

// 注意:Command接口的实现类一定要定义在名称形式如“com.*.wechat.mvc.commands”的包中,因为在applicationContext-servlet.xml配置文件中已经指明了要对这种形式的包进行扫描以发现可以自动装配的Bean

package com.user.wechat.mvc.commands;

import java.sql.Timestamp;

import java.util.Random;

import org.springframework.stereotype.Component;

import com.halo.wechat.messages.ClickEvent;

import com.halo.wechat.messages.Event;

import com.halo.wechat.messages.LocationEvent;

import com.halo.wechat.messages.LocationMessage;

import com.halo.wechat.messages.Message;

import com.halo.wechat.messages.MsgType;

import com.halo.wechat.messages.SubscribeEvent;

import com.halo.wechat.messages.TextMessage;

import com.halo.wechat.mvc.commands.Command;

import com.halo.wechat.mvc.commands.CommandException;

/**

  • @file UserCommand.java

  • @author Junior

  • @date 2015年8月9日 上午11:21:44

  • @version 1.0

*/

// 注意:此处一定要加上@Component注解,这样Spring MVC框架才可以扫描到开发者自定义的实现类并自动装配到WTF中,这样无需编写任何代码即可让WTF自动调用开发者自己的消息和事件处理方法。

@Component

public class UserCommand implements Command {

     // 消息处理方法,在接收到微信公众平台发送的消息时,WTF会自动调用该方法。

     @Override

     public Message processMessage(Message receiveMessage) throws CommandException {

               Message responseMessage = null;

               System.out.println("Receive a " + receiveMessage.getClass().getSimpleName() + " type " + receiveMessage.getMsgType());



               Random rand = new Random();

               long msgId = rand.nextLong();

               String responseText = "你好啊!";

               // 此处可根据receiveMessage.getMsgType()判断接收到的微信公众平台消息类型,消息类型常量定义在MsgType类中,例如MsgType.TEXT是文本消息,详见MsgType类的说明。

               if (MsgType.LOCATION.equals(receiveMessage.getMsgType())) {

                        LocationMessage locationMsg = (LocationMessage) receiveMessage;

                        responseText = "你目前位于东经" + String.valueOf(locationMsg.getLocation_Y()) + "度,北纬" + String.valueOf(locationMsg.getLocation_X()) + "度。地点:"

                                           + locationMsg.getLabel();

               }



               // 开发者可构建自己的回复消息,如果不需要回复任何消息,可直接retrun null

               responseMessage = new TextMessage(receiveMessage.getFromUserName(), receiveMessage.getToUserName(), new Timestamp(System.currentTimeMillis()),

                                 MsgType.TEXT, responseText, msgId);

               return responseMessage;

     }



     // 事件处理方法,在接收到的微信公众平台消息是事件类型时,WTF会自动调用该方法。

     @Override

     public Message processEvent(Event receiveEvent) throws CommandException {

               Message responseMessage = null;

               String responseText = "建设中...";

               // 以下方法可以判断事件类型。

               if (receiveEvent instanceof ClickEvent) {

                        ClickEvent clickEvent = (ClickEvent) receiveEvent;

                        // 以下方法可以判断菜单点击事件中,用户具体点击的是哪一个菜单。

                        if ("tip".equals(clickEvent.getEventKey())) {

                                 responseText = "你想要回复的内容……";

                        }

               } else if (receiveEvent instanceof SubscribeEvent) {

                        responseText = "你想要回复的内容……";

               } else if (receiveEvent instanceof LocationEvent) {

                        LocationEvent lctnEvnt = (LocationEvent) receiveEvent;

                        responseText = "你目前位于东经" + String.valueOf(lctnEvnt.getLongitude()) + "度,北纬" + String.valueOf(lctnEvnt.getLatitude()) + "度。";

               }



               // 开发者可构建自己的回复消息,如果不需要回复任何消息,可直接retrun null

               Random rand = new Random();

               long msgId = rand.nextLong();

               responseMessage = new TextMessage(receiveEvent.getFromUserName(), receiveEvent.getToUserName(), new Timestamp(System.currentTimeMillis()), MsgType.TEXT, responseText, msgId);

               return responseMessage;

     }

}

至此,你已经可以开始开发自己的微信公众号了!在开发中你还需要创建菜单、向微信公众平台请求二维码等更多功能,WTF以Capability的形式封装了这些能力接口,以更简单方便的形式提供给开发者调用,更多高级的接口功能请参考以下的教程。

1.3 依赖包

WTF利用了Spring、Log4J等诸多框架,因此你需要将以下包也加入到项目中,方法同加入WTF的jar包一样。

依赖包:

httpcomponent-4.5

json-2.4

log4j-2.3

spring-3.2.9

spring-related

依赖包下载地址:http://115.159.67.204/Tutorial/Download/wtf-dependencies.rar

2 教程

2.1 基本功能

2.1.1 获取接口调用凭据

在WTF中提供了AccessCapability类,该类实现AccessAbility接口,提供获取全局唯一票据(access_token)的方法,和获取微信服务器的IP地址方法。请看AccessCapability类的说明:

获取微信接口调用凭据,本类实现了获取全局唯一票据(access_token)的方法,和获取微信服务器的IP地址方法。在微信开发框架中,在接收任何微信推送消息和事件之前都会调用本类的方法,获取接口调用凭据。用户也可以在自己的项目中的任何地方实例化本类的对象,来调用本类的方法,前提是用户项目是基于Spring框架的web应用。

以下是一个使用AccessCapability类获取全局唯一票据(access_token)的例子:

public class AccessCapabilityTest {

     @Autowired

     private AccessAbility accessAbility;



     /**

      * 获取接口调用凭据(access_token)的方法

      */

     public void getAccessToken() {

               AccessTokenBean accessTokenBean = null;

               try {

                        accessTokenBean = accessAbility.getAccessToken();

               } catch (CapabilityException e) {

                        // TODO Auto-generated catch block

                        e.printStackTrace();

               }



               System.out.println(accessTokenBean.getAccess_token() + "|" + String.valueOf(accessTokenBean.getExpires_in()) + "|" + String.valueOf(accessTokenBean.getRefreshTime()) + "|" + String.valueOf(accessTokenBean.getErrcode()) + "|" + accessTokenBean.getErrmsg());

     }



     /**

      * 获取微信公众平台服务器地址列表的方法

      */

     public void testGetServerAddr() {

               ServerAddrBean serverAddrBean = null;

               try {

                        serverAddrBean = accessAbility.getServerAddr();

               } catch (CapabilityException e) {

                        // TODO Auto-generated catch block

                        e.printStackTrace();

               }



               for (String serverAddr : serverAddrBean.getIp_list()) {

                        System.out.println(serverAddr);

               }

     }

}

从上面的例子可以看出,accessAbility对象是可以利用Spring框架自动装配的。实际上,只要开发者在web.xml文件中配置了Spring框架的DispatchServlet去读取classpath:com/halo/wechat/config/applicationContext-servlet.xml上下文(见1.2节的第二步),那么所有的Ability接口都可以用@Autowired注解来自动装配。

开发者可能会有疑问:获取接口调用凭据是需要提供公众号的app_id和app_secret的,那么这两个参数在哪里设置呢?

实际上开发者需要在项目的classpath路径下提供一个名为“wechat.properties”的配置文件,该文件的内容如下:

app_id=xxxxxxxxx // 设置你的app_id

app_secret=xxxxxxxxxxxxxxx // 设置你的app_secret

token=xxxxxxxx // 设置你的token,验证服务器地址的有效性用的。

WTF在调用请求创建菜单、请求创建二维码等需要access_token的接口时,会自动调用AccessCapability来获取access_token。公布AccessCapability类是为了给开发者更多的自主选择,一般情况下开发者无需自己调用该接口。

2.1.2 自定义菜单管理

自定义菜单管理CustomMenuCapability实现CustomMenuAbility接口,提供对微信公众平台自定义菜单管理的创建、查询、删除菜单功能的调用。

在WTF中还有MenuBean和MenuResultBean两个实体类都是与自定义菜单管理相关的,MenuBean保存开发者准备创建的菜单结构,该类可以通过JSONUtils工具类转换成json字符串。如你所料,MenuBean类是自定义菜单创建方法的输入参数。

MenuResultBean类用来保存菜单查询接口返回的菜单结构,因为菜单查询接口返回的json字符串结构跟菜单创建接口的json结构不同。可以通过JSONUtils工具类从json字符串转换得到该类的对象。

以下的例子演示自定义菜单的创建:

public void bTestCreateMenu() {

     // ResultBean是一个标准的用于接收微信公众平台接口调用结果的类

     ResultBean resultBean = null;

              

     MenuBean menu = new MenuBean();



     // 创建二级菜单

// ButtonBean是一个成员内部类,因此要用menu.new ButtonBean()这种方式来创建

     ButtonBean buttonA = menu.new ButtonBean();

     buttonEnv.setKey("click_button_1");

     buttonEnv.setName("演示菜单1");

     buttonEnv.setType(ButtonBean.BUTTON_TYPE_CLICK);



     ButtonBean buttonB = menu.new ButtonBean();

     buttonJava.setKey("click_button_2");

     buttonJava.setName("演示菜单2");

     buttonJava.setType(ButtonBean.BUTTON_TYPE_CLICK);



     // 将二级菜单放进一个List

     List<ButtonBean> subbuttons = new LinkedList<ButtonBean>();

     subbuttons.add(buttonA);

     subbuttons.add(buttonB);



     // 创建一级菜单,然后将二级菜单的List放进一级菜单

     ButtonBean buttonRootA = menu.new ButtonBean();

     buttonArticle.setName("一级菜单1");

     buttonArticle.setSub_button(subbuttons);



     // 创建另一个二级菜单

     ButtonBean buttonC = menu.new ButtonBean();

     buttonC.setUrl("http://your.url/");

     buttonC.setName("跳转链接按钮");

     buttonC.setType(ButtonBean.BUTTON_TYPE_VIEW);



     // 再放进一个List

     List<ButtonBean> subbuttonsB = new LinkedList<ButtonBean>();

     subbuttonsB.add(buttonC);



     // 又创建一个一级菜单,然后将第二个List放进一级菜单

     ButtonBean buttonRootB = menu.new ButtonBean();

     buttonMenual.setName("一级菜单2");

     buttonMenual.setSub_button(menualSubbuttons);



     // 也可以创建一个可以直接点击的一级菜单

     ButtonBean buttonRootC = menu.new ButtonBean();

     buttonRootC.setKey("menu_a");

     buttonRootC.setName("直接点我");

     buttonRootC.setType(ButtonBean.BUTTON_TYPE_CLICK);



     // 将所有的一级菜单再放进一个List

     List<ButtonBean> buttons = new LinkedList<ButtonBean>();

     buttons.add(buttonRootA);

     buttons.add(buttonRootB);

     buttons.add(buttonRootC);



     // 最后将List放进menu

     menu.setButton(buttons);



     try {

               // 调用菜单创建方法,将menu作为参数传入

// 这里的customMenuAbility是类私有成员,用@Autowired注解自动注入的

               resultBean = customMenuAbility.createMenu(menu);

     } catch (CapabilityException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

     }



     System.out.println(String.valueOf(resultBean.getErrcode()) + "|" + resultBean.getErrmsg());

}

2.1.3 自动创建菜单

在WTF v1.0.0.2版本里,我加入了自动创建菜单的监听器CustomMenuLoadListener,这个监听器在web应用启动时检查在web应用根目录下是否有文件名为customMenu.json的文件,如果有,则删除原微信公众号的菜单,按文件内容创建新菜单。

customMenu.json文件的内容要符合微信公众平台自定义菜单创建接口标准。

CustomMenuLoadListener需要在web.xml中配置才能生效,配置格式如下:

com.halo.servlet.listeners.CustomMenuLoadListener

注意:CustomMenuLoadListener的配置需要放在filter和ContextLoaderListener(如果有的话)的配置之后,servlet(如果有的话)的配置之前。

开发者可以在web.xml的context-param节中指定自己的菜单文件名,param-name为customMenuLocation,如下例:

customMenuLocation

myMenu.json

注意:

  1.     菜单文件只能有一个,不要试图添加多个菜单文件名,那样找不到任何菜单文件;
    
  2.     修改或添加新的菜单文件后,需重启web应用才会生效;
    
  3.     如果要删除原菜单又不创建新菜单,请在web应用根目录下放置一个名为“deleteMenu.json”的空文件;
    
  4.     菜单文件也可以放在web应用根目录下的任意子目录中,在配置文件路径时使用相对于web应用根目录的路径,例如:resources\myMenu.json
    

2.1.4 接收消息能力接口

MessageCapability是WTF最核心,最重要的一个能力类。WTF用本类来处理微信公众平台推送的消息和事件,并调用开发者定义的Command接口实现类,然后将用户回复的消息对象转换成XML字符串,回复给微信公众平台。

WTF对MessageCapability和开发者定义的Command接口实现类的调用是完全自动的,开发者只需编写自己的消息处理逻辑。当然,WTF的框架是非常灵活的,开发者完全也可以在自己的项目中实例化本类,并调用本类的方法来处理微信公众平台推送消息和事件。

以下是对本类中三个重要方法的说明:

方法:public MsgType receiveMessage(HttpServletRequest request) throws CapabilityException;

方法说明:从HttpServletRequest对象中取得微信公众平台推送的消息或事件,并将xml格式的消息(或事件)转换成MsgType及其子类型的对象。

方法参数:request 微信公众平台的post请求

返回值:从xml格式的消息(或事件)转换成的MsgType类型的对象,其实际对象类型可通过getMsgType方法获得。

方法:public Message executeCommand(Command command, MsgType message) throws CapabilityException

方法说明:执行用户自定义的Command接口实现类。

方法参数:command 用户自定义的Command接口实现类。

方法参数:message 微信公众平台推送的消息或事件。

返回值:用户处理结束后的回复消息对象。

方法:public void responseMessage(HttpServletResponse response, Message message) throws CapabilityException

方法说明:将用户的回复消息回复给微信公众平台。

方法参数:response HttpServletResponse对象,通过该对象回复消息。

方法参数:message 用户的回复消息。

2.2 帐号管理功能

2.2.1 生成带参数的二维码

为了满足用户渠道推广分析的需要,公众平台提供了生成带参数二维码的接口。

使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。 目前有2种类型的二维码:

1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的7天(即604800秒)后过期,但能够生成较多数量。

临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景。

2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。

QrcodeCapability类提供了对以上2种二维码的申请创建和图片文件获取方法。

以下代码演示如何申请创建一个带参数的临时二维码:

public QrcodeResultBean getRegistQrcode(int sceneId) {

     QrcodeResultBean qrcodeResultBean = null;

     QrcodeAbility qrcodeAbility = (QrcodeAbility) SpringUtils.getBean("qrcodeAbility");

     if (null == qrcodeAbility) {

               return null;

     }

     try {

               qrcodeResultBean = qrcodeAbility.getTemporaryQrcode(EXPIRE_TIME, sceneId);

     } catch (CapabilityException e) {

               e.printStackTrace();

     }

     return qrcodeResultBean;

}

从实例可见申请创建一个临时二维码的过程非常简单,qrcodeAbility接口和实现类已经在spring配置文件“applicationContext-wechat.xml”中声明了,还记得吗,applicationContext-wechat.xml是在1.2节中提到过的,需配置spring框架的ContextLoadListener去加载的上下文配置文件。申请创建永久二维码的过程是类似的,只不过调用的方法不同。

以下演示如何用ticket获取已创建的二维码图片文件:

private String getQrcodeImage(String ticket) throws CapabilityException {

     QrcodeAbility qrcodeAbility = (QrcodeAbility) SpringUtils.getBean("qrcodeAbility");

     if (null == qrcodeAbility) {

               return null;

     }

     // 二维码图片文件默认下载到classpath目录下,建议用File.renameTo(File)方法另存到开发者指定的位置

File downloadFile = qrcodeAbility.getQrcodeImage(ticket);

     // 此处用ticket做文件名,因此需将ticket中可能有的非法字符替换掉

     String fileName = ticket.replace('\\', 'x').replace('/', 'x').replace(':', 'x').replace('*', 'x').replace('?', 'x').replace('\"', 'x').replace('<', 'x').replace('>', 'x').replace('|', 'x').replace('\"', 'x') + ".jpg";

     String saveAsFileName = SpringUtils.getWebApplicationContext()

.getServletContext().getRealPath("/images")

  • File.separator + fileName;

       File saveAsFile = new File(saveAsFileName);
    
       downloadFile.renameTo(saveAsFile);
    
    
    
       return fileName;
    

}

2.3 素材管理功能

公众号经常有需要用到一些临时性的多媒体素材的场景,例如在使用接口特别是发送消息时,对多媒体文件、多媒体消息的获取和调用等操作,是通过media_id来进行的。素材管理接口对所有认证的订阅号和服务号开放(注:自定义菜单接口和素材管理接口向第三方平台旗下未认证订阅号开放)。通过本接口,公众号可以新增临时素材(即上传临时多媒体文件)。

请注意:

1、对于临时素材,每个素材(media_id)会在开发者上传或粉丝发送到微信服务器3天后自动删除(所以用户发送给开发者的素材,若开发者需要,应尽快下载到本地),以节省服务器资源。

2、media_id是可复用的。

3、素材的格式大小等要求与公众平台官网一致。具体是,图片大小不超过2M,支持bmp/png/jpeg/jpg/gif格式,语音大小不超过5M,长度不超过60秒,支持mp3/wma/wav/amr格式

除了3天就会失效的临时素材外,开发者有时需要永久保存一些素材,可以通过本接口管理永久素材。

2.3.1 获取临时素材

方法:public File getMedia(String mediaId) throws CapabilityException;

方法说明:公众号可以使用本接口获取临时素材(即下载临时的多媒体文件)。请注意,视频文件不支持https下载。

方法参数:mediaId 媒体文件ID

返回值:下载的媒体文件(File类型),可以用renameTo方法将文件另存到指定的位置。

2.3.2 获取永久素材

方法:public MaterialResultBean getMaterial(String mediaId) throws CapabilityException;

方法说明:

在新增了永久素材后,开发者可以根据media_id来获取永久素材。

请注意:

1、获取永久素材也可以获取公众号在公众平台官网素材管理模块中新建的图文消息、图片、语音、视频等素材(但需要先通过获取素材列表来获知素材的media_id)

2、临时素材无法通过本接口获取

3、除图文、视频以外其他类型的素材,需通过downloadMaterial()方法下载

方法参数:mediaId 媒体文件ID

返回值:

MaterialResultBean

如果请求的素材为图文消息,则图文内容通过MaterialResultBean的getNews_item()方法获得,getNews_item()方法返回一个List,其中可能包括多条图文内容。

如果请求的是视频消息素材,则通过MaterialResultBean的getTitle()、getDescription()、getDown_url()方法分别获得视频素材的标题、描述和下载地址。

2.3.3 下载永久素材

方法:public File downloadMaterial(String mediaId) throws CapabilityException;

方法说明:除图文、视频以外其他类型的素材消息,则响应的直接为素材的内容,开发者可以自行保存为文件。

方法参数:mediaId 媒体文件ID

返回值:下载的素材文件(File类型),可以用renameTo方法将文件另存到指定的位置。

2.3.4 获取素材总数

方法:public MaterialCountBean getMaterialCount() throws CapabilityException;

方法说明:获取永久素材的总数。

返回值:MaterialCountBean

2.3.5 获取素材列表

方法:public File downloadMaterial(String mediaId) throws CapabilityException;

方法说明:

在新增了永久素材后,开发者可以分类型获取永久素材的列表。

1、获取永久素材的列表,也会包含公众号在公众平台官网素材管理模块中新建的图文消息、语音、视频等素材(但需要先通过获取素材列表来获知素材的media_id)

2、临时素材无法通过本接口获取

方法参数:

type:素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)。MaterialAbility接口中定义了这几种类型的常量“MATERIAL_TYPE_IMAGE”、“MATERIAL_TYPE_VIDEO”、“MATERIAL_TYPE_VOICE”、“MATERIAL_TYPE_NEWS”

offset:从全部素材的该偏移位置开始返回,0表示从第一个素材返回

count:返回素材的数量,取值在1到20之间

返回值:

MaterialListBean

获取的图文、图片或视频素材都通过MaterialListBean的getItem()方法获得,该方法返回一个List,可能有多个元素,每个元素都是一个Item对象。

图文素材的具体内容通过Item对象的getContent()方法获得,其他素材通过getName()、getUrl()方法获得名称和下载地址。

2.3.6 代码示例

以下代码演示如何获取永久素材的数量,列表及下载图文素材和图片到本地:

     public String saveNewsToLocal(short materialCount) {

               // 在applicationContext-wechat.xml文件中已经声明了素材管理能力接口materialAbility的bean,此处用SpringUtils.getBean()方法直接获取

               MaterialAbility materialAbility = (MaterialAbility) SpringUtils.getBean("materialAbility");

               MaterialCountBean materialCountBean = null;

               try {

                        // 获取素材总数

                        materialCountBean = materialAbility.getMaterialCount();

               } catch (CapabilityException e) {

                        System.out.println("Get material count error.");

               }



               short count = materialCountBean.getNews_count() > materialCount ? materialCount : materialCountBean.getNews_count();

               short offset = (short) (materialCountBean.getNews_count() > materialCount ? materialCountBean.getNews_count() - materialCount : 0);



               if (0 == count) {

                        return "没有永久素材可下载。";

               }



               MaterialListBean materialListBean = null;

               try {

                        // 获取图文永久素材

                        materialListBean = materialAbility.batchGetMaterial(MaterialAbility.MATERIAL_TYPE_NEWS, offset, count);

               } catch (CapabilityException e) {

                        System.out.println("Batch get material error.");

               }



               String savedRecord = "<table><th colspan='4'>共下载" + String.valueOf(count) + "条素材</th>";

               for (MaterialListBean.Item item : materialListBean.getItem()) {

                        for (NewsItem newsItem : item.getContent().getNews_item()) {

                                 File bigPicFile;

                                 try {

                                           // 下载图文素材的封面图片

                                           bigPicFile = materialAbility.downloadMaterial(newsItem.getThumb_media_id());

                                 } catch (CapabilityException e) {

                                           System.out.println("Download cover picture error.");

                                 }

                                 String saveAsPath = SpringUtils.getWebApplicationContext().getServletContext().getRealPath("image/");

                                 String saveAsFileName = newsItem.getThumb_media_id() + ".jpg";

                                 File saveAsFile = new File(saveAsPath + File.separator + saveAsFileName);

                                 bigPicFile.renameTo(saveAsFile);



                                 // 这里演示将图文素材保存到本地数据库中

                                 String bigPicUrl = "http://115.159.67.204/WeChat/images/" + saveAsFileName;

                                 ArticleCatalog articleCatalog = new ArticleCatalog(newsItem.getTitle(), newsItem.getDigest(), bigPicUrl, DEFAULT_THUMB_IMG_URL, newsItem.getUrl(), new Date());

                                 Integer id = articleCatalogDao.save(articleCatalog);



                                 savedRecord += "<tr>";

                                 savedRecord += "<td>" + String.valueOf(id) + "</td>";

                                 savedRecord += "<td>" + newsItem.getTitle() + "</td>";

                                 savedRecord += "<td>" + bigPicUrl + "</td>";

                                 savedRecord += "<td>" + newsItem.getUrl() + "</td>";

                                 savedRecord += "</tr>";

                        }

               }

               savedRecord += "</table>";



               return savedRecord;

     }

2.4 用户管理功能

2.4.1 设置用户备注名

开发者可以通过该接口对指定用户设置备注名,公众平台开发者文档中声称该接口暂时只开放给微信认证的服务号。经过测试,实际上订阅号也可以成功调用该接口。

以下是该接口函数的定义和说明:

/**

  • 开发者可以通过该接口对指定用户设置备注名,该接口暂时开放给微信认证的服务号。
  • @param String
  • openId 用户标识
  • @param String
  • remark 新的备注名,长度必须小于30字符
  • @return 微信公众平台接口调用返回码和详细说明 */ public ResultBean updateRemark(String openId, String remark) throws CapabilityException;

以下代码演示如何调用本接口:

public void updateRemark() throws CapabilityException { ResultBean resultBean = userManagementAbility.updateRemark("oANCiuUnCPMDzOH89-JravbLFBUk", "VIP");

System.out.println("errcode: " + resultBean.getErrcode()); System.out.println("errmsg: " + resultBean.getErrmsg()); } 2.4.2 获取用户基本信息

在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同 一用户的openid不同)。公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。

接口函数定义和说明:

/**

  • 公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。
  • @param String
  • openId 普通用户的标识,对当前公众号唯一
  • @param String
  • lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语
  • @return 获取用户基本信息接口返回的用户信息,错误时微信会返回错误码等信息 */ public UserInfoBean getUserInfo(String openId, String lang) throws CapabilityException;

以下代码演示如何调用获取用户基本信息接口:

public void getUserInfo() throws CapabilityException { UserInfoBean userInfoBean = userManagementAbility.getUserInfo("oANCiuUnCPMDzOH89-JravbLFBUk", "zh_CN");

System.out.println("subscribe: " + userInfoBean.getSubscribe()); System.out.println("nickname: " + userInfoBean.getNickname()); System.out.println("sex: " + userInfoBean.getSex()); System.out.println("country: " + userInfoBean.getCountry()); System.out.println("province: " + userInfoBean.getProvince()); System.out.println("city: " + userInfoBean.getCity()); System.out.println("language: " + userInfoBean.getLanguage()); System.out.println("headimgurl: " + userInfoBean.getHeadimgurl()); System.out.println("subscribe_time: " + new Date(userInfoBean.getSubscribe_time())); } 2.4.3 获取用户列表

公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的)组成。一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。

接口函数定义和说明:

/**

  • 公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID组成。
  • 一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
  • @param String
  • nextOpenId 第一个拉取的OPENID,为null时默认从头开始拉取
  • @return UserListBean 关注者列表数据
  • @throws CapabilityException */ public UserListBean getUserList(String nextOpenId) throws CapabilityException;

代码演示:

public void getUserList() throws CapabilityException { UserListBean userListBean = userManagementAbility.getUserList("");

System.out.println("total: " + userListBean.getTotal()); System.out.println("count: " + userListBean.getCount());

if (null != userListBean.getData()) { for (String openId : userListBean.getData().getOpenid()) { System.out.println("openid: " + openId); } }

System.out.println("next_openid: " + userListBean.getNext_openid()); System.out.println("errcode: " + userListBean.getErrcode()); System.out.println("errmsg: " + userListBean.getErrmsg()); }

3 当前版本限制

WTF 1.0版本尚未提供以下微信公众平台接口:

  1.     未提供加密消息的接收和回复功能;
    
  2.     未提供素材管理的部分功能,包括新增、删除、修改临时和永久素材;
    
  3.     未提供用户管理的部分功能,包括分组管理、网页授权获取用户基本信息;
    
  4.     未提供长链接转短链接功能;
    
  5.     未提供数据统计接口功能;
    
  6.     未提供微信小店管理接口功能;
    
  7.     未提供微信卡券管理接口功能;
    
  8.     未提供微信门店管理接口功能;
    
  9.     未提供微信智能接口功能;
    
  10. 未提供设备功能接口;
    
  11. 未提供多客服功能;
    
  12. 未提供摇一摇周边功能;
    
  13. 未提供微信连Wi-Fi功能。
    

4 版本计划

在下一个版本中,我计划继续开发以下功能:

  1.     加密消息的接收和回复功能;
    
  2.     素材管理的所有功能,包括新增、获取、删除、修改临时和永久素材;
    
Clone this wiki locally