基于jfinal-weixin sdk微信二次开发(入门篇)

    既然是入门篇,那么就从最基本的开始。一下内容全部基于 jfinal 框架 和 jfinal-weixin  sdk 介绍使用。

    我这里推荐使用maven项目,jfinal官方也提供现成项目下载,这里不在对创建项目做具体介绍,大家也可以直接上官方下载一个 jfinal项目 导入本地即可。

    1.首先创建我们的wechat  maven项目,我的项目结构如下:

    143342_8bZH_2249701.png

   

 既然是maven项目,那么少不了 pom文件的jar管理,我们需要导入以下jfinal相关jar

          <dependencies>
	    <dependency>
	    	<groupId>com.jfinal</groupId>
	    	<artifactId>jetty-server</artifactId>
	    	<version>8.1.8</version>
	    	<scope>provided</scope>
	    </dependency>
		<!-- jfinal 核心har -->
		<dependency>
			<groupId>com.jfinal</groupId>
			<artifactId>jfinal</artifactId>
			<version>2.0</version>
		</dependency>
		<!-- jfinal-weixin jar -->
		<dependency>
			<groupId>com.jfinal</groupId>
			<artifactId>jfinal-weixin</artifactId>
			<version>1.4</version>
		</dependency>
		<!-- 以下是必备的第三方依赖jar -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.4.3</version>
		</dependency>
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>
		<dependency>
			<groupId>jaxen</groupId>
			<artifactId>jaxen</artifactId>
			<version>1.1.6</version>
		</dependency>
		<dependency>
    		    <groupId>commons-codec</groupId>
    		    <artifactId>commons-codec</artifactId>
    		    <version>1.9</version>
	        </dependency>
		<dependency>
		    <groupId>org.freemarker</groupId>
		    <artifactId>freemarker</artifactId>
		    <version>2.3.20</version>
		</dependency>
	</dependencies>

   

    接下来是个比较核心重要的部分,jfinal-weixin sdk源码中其实已经提供好了 继承 JFinalConfig 核心类的处理,但是我们这里并不去使用,为了自己项目的随意性和方便后期代码的维护等一系列可能发生的,我建议自己去创建一个 并集成 JFinalConfig核心类

package com.jfinal.wechat.config;

import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;

/**
 * JfinalWechatConfig 核心部分
 * @author xkjava
 *
 */
public class JfinalWechatConfig extends JFinalConfig {

	@Override
	public void configConstant(Constants me) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configRoute(Routes me) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configPlugin(Plugins me) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configInterceptor(Interceptors me) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configHandler(Handlers me) {
		// TODO Auto-generated method stub
		
	}

}


以上就是我们需要的核心类,当然只是需要这个空类是不行的,我们需要稍微加一点内容,那么具体内容如下

首先 在configConstant 方法加载我们的配置文件,这里我们需要在resources 目录下 创建我们的配置文件,jfinal官方一直是习惯使用 txt文件的,那么我们就使用txt作为配置文件,这里我来创建一个 wechatConfig.txt。

    那么在这里呢,我们是不做任何与数据库项目的操作的,所以只要放入对应微信的配置即可,这里我就直接复制波老师的配置 修改 对应的值即可,一下是 wechatConfig.txt 文件内容

 # 微信服务器回调所用的 token
token=与测试号的token要一致,自定义

# 测试用的账号
appId=唯一值,对应上测试号的appId即可
appSecret=不唯一值,对应上测试号的appSecret即可

#是否对消息进行加密,是否对消息进行加密,对应于微信平台的消息加解密方式,false支持明文模式及兼容模式,true支持安全模式及兼容模式
#encryptMessage=true
#encodingAesKey=yourEncodingAesKey

那么这里我是使用了微信的测试帐号,测试帐号目前我并没找到加密处理模块,所以我们暂时先不用这个功能。

测试号登录地址:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

点击登录,只要拿自己的公众号扫描即可登录属于自己的测试帐号,方便快捷。

151518_LRlT_2249701.png

好了,这里我们继续回到我们 JfinalWechatConfig 类,这里需要在configConstant 方法加载我们的配置文件。

修改后的JfinalWechatConfig 类

package com.jfinal.wechat.config;

import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;

/**
 * JfinalWechatConfig 核心部分
 * @author xkjava
 *
 */
public class JfinalWechatConfig extends JFinalConfig {

	@Override
	public void configConstant(Constants me) {
		//加载配置文件
		PropKit.use("wechatConfig.txt");
		//控制台输出消息内容
		me.setDevMode(PropKit.getBoolean("devMode", true));
	}

	@Override
	public void configRoute(Routes me) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configPlugin(Plugins me) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configInterceptor(Interceptors me) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configHandler(Handlers me) {
		// TODO Auto-generated method stub
		
	}

}


接下来需要配置一下我们的 web.xml文件了

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
	<filter>
		<filter-name>jfinal</filter-name>
		<filter-class>com.jfinal.core.JFinalFilter</filter-class>
		<init-param>
			<param-name>configClass</param-name>
			<param-value>com.jfinal.wechat.config.JfinalWechatConfig</param-value>
		</init-param>
	</filter>
	
	<filter-mapping>
		<filter-name>jfinal</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

注意:这里的 init-param 节点下的 param-value 指向的是我们刚自己创建的JfinalWechatConfig 类

到此呢,算是搭建了把jfianl 框架整合好了,接下来才是属于微信的部分,不要怕累,好的东西慢慢迭代,仔细往下看:

微信呢,其实分两个类型的服务,一个是消息接口服务,一个是api接口服务。比如我们关注后回复消息,直接在聊天框进行消息对话,或音频,图文,文本等,这些属于消息服务; 比如我们支付,网页授权,模版消息,创建菜单等,属于api接口。

    为了区分开,我们在构建代码时,建议大家将消息服务与api服务分开处理,至少区分的干净,舒服,至于更细致化的业务层面,开发者可根据自己的需求来区分处理。 这篇博文是带大家入门,在这里我们目前只创建一个消息服务类,api服务希望将在后面继续介绍使用。

package com.jfinal.wechat.config;

import com.jfinal.core.Controller;

/**
 * 微信消息服务处理
 * @author xkjava
 *
 */
public class WechatMsgController extends Controller{


	/**
	 * 消息入口
	 */
	public void index(){
		
	}
	
}

消息服务 处理 其实就一个核心的方法,就是我们微信公众号平台的 URL 所指向的路由地址。

注意:

  1. 官方源码提供在消息入口方法上加拦截器,我们照搬(至于拦截器处理的原因,后面会介绍)。jfianl-weixin sdk已经封装了各种好用的内置api,所以,这里我们直接使用波老师内置的就可以。

接下来我们创建一个拦截器,在进入 消息入口 index 方法之前执行,目的是在用户消息处理之前,先将当前公众号信息绑定到当前线程上,这样的处理是方便后期多公众号的操作(多公众号处理希望后续介绍,波老师的 MsgInterceptor 拦截器大家可以去看下源码,这里我根据自己的需求少做修改,改动不大,至于说明全部加在注释上)。

package com.jfinal.wechat.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Logger;
import com.jfinal.wechat.config.WechatMsgController;
import com.jfinal.weixin.sdk.api.ApiConfigKit;
import com.jfinal.weixin.sdk.kit.SignatureCheckKit;

/**
 * 消息服务 拦截器
 * @author xkjava
 *
 */
public class WechatMsgInterceptor implements Interceptor  {
	
	private static Logger log = Logger.getLogger(WechatMsgInterceptor.class);

	@Override
	public void intercept(Invocation inv) {
		Controller controller = inv.getController();
		if (controller instanceof WechatMsgController == false)
			throw new RuntimeException("控制器需要继承 WechatMsgController");
		
		try {
		// 将 ApiConfig 对象与当前线程绑定,以便在后续操作中方便获取该对象: 
		ApiConfigKit.getApiConfig();
		ApiConfigKit.setThreadLocalApiConfig(((WechatMsgController )controller).getApiConfig());
			
		// 如果是服务器配置请求,则配置服务器并返回
		if (isConfigServerRequest(controller)) {
			configServer(controller);
			return ;
		}
			
		// 签名检测
		if (checkSignature(controller)) {
			inv.invoke();
		}
		else {
			controller.renderText("签名验证失败,请确定是微信服务器在发送消息过来");
		}
	}
	finally {
		ApiConfigKit.removeThreadLocalApiConfig();
	}
		
    }
	

	/**
	 * 检测签名
	 */
	private boolean checkSignature(Controller controller) {
		String signature = controller.getPara("signature");
		String timestamp = controller.getPara("timestamp");
		String nonce = controller.getPara("nonce");
		if (StrKit.isBlank(signature) || StrKit.isBlank(timestamp) || StrKit.isBlank(nonce))                {
		    controller.renderText("check signature failure");
		    return false;
		}
		
		if (SignatureCheckKit.me.checkSignature(signature, timestamp, nonce)) {
			return true;
		}
		else {
			log.error("check signature failure: " +
					" signature = " + controller.getPara("signature") +
					" timestamp = " + controller.getPara("timestamp") +
					" nonce = " + controller.getPara("nonce"));
			
			return false;
		}
	}
	
	/**
	 * 是否为开发者中心保存服务器配置的请求
	 */
	private boolean isConfigServerRequest(Controller controller) {
		return StrKit.notBlank(controller.getPara("echostr"));
	}
	
	/**
	 * 配置开发者中心微信服务器所需的 url 与 token
	 * @return true 为config server 请求,false 正式消息交互请求
	 */
	public void configServer(Controller c) {
	    // 通过 echostr 判断请求是否为配置微信服务器回调所需的 url 与 token
	    String echostr = c.getPara("echostr");
	    String signature = c.getPara("signature");
            String timestamp = c.getPara("timestamp");
            String nonce = c.getPara("nonce");
	    boolean isOk = SignatureCheckKit.me.checkSignature(signature, timestamp, nonce);
	    if (isOk)
		c.renderText(echostr);
	    else
		log.error("验证失败:configServer");
	}

}

以上是我在波老师的源码中copy过来的代码,自己只在interceptor 方法中修改了 消息服务 对应的 WechatMsgController

另外三个方法大家看注释,及调用顺序即可明白。

拦截去做好了回到我们的消息服务 WechatMsgController,此时的WechatMsgController 应该是这样的,在 index 方法上添加了拦截器注解,添加了获取 apiconfig对象方法 (当然这也是波老师的神作)

package com.jfinal.wechat.config;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.kit.PropKit;
import com.jfinal.wechat.interceptor.WechatMsgInterceptor;
import com.jfinal.weixin.sdk.api.ApiConfig;

/**
 * 微信消息服务处理
 * @author xkjava
 *
 */
public class WechatMsgController extends Controller{
	
	/**
	 * 消息入口
	 * 
	 * 加载WechatMsgInterceptor拦截器,在处理index之前 绑定ApiConfig
	 */
	@Before(WechatMsgInterceptor.class)
	public void index(){
		
	}
	
	/**
	 * 此方法在拦截器调用,根据 wechatConfig.txt 配置文件消息 封装 ApiConfig对象,
	 * ApiConfig对象封装了 微信的token appid等信息,有兴趣的同学可以去看下源码
	 * 拦截器内调用此方法返回ApiConfig对象后将次对象绑定在当前线程,这样方便后面具体业务上的调用
	 * 关于线程部分的处理,可以去看源码。如有问题,可以留言,我会根据大家的问题再来做具体介绍。
	 * 当然大神们是不需要的
	 * @return
	 */
	public ApiConfig getApiConfig(){
		ApiConfig apiConfig = new ApiConfig();
		apiConfig.setToken(PropKit.get("token"));
		apiConfig.setAppId(PropKit.get("appId"));
		apiConfig.setAppSecret(PropKit.get("appSecret"));
		/**
		 *  是否对消息进行加密,对应于微信平台的消息加解密方式:
		 *  1:true进行加密且必须配置 encodingAesKey
		 *  2:false采用明文模式,同时也支持混合模式
		 *  
		 *  这里暂时不对消息加解密做处理
		 */
		/*apiConfig.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
		apiConfig.setEncodingAesKey(PropKit.get("encodingAesKey", "setting it in config file"));*/
		return apiConfig;
	}
	

}

好了,接下来就是对 index 的处理了

首先我们处理消息接收响应转换处理部分(还是直接copy源码):

package com.jfinal.wechat.config;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Logger;
import com.jfinal.wechat.interceptor.WechatMsgInterceptor;
import com.jfinal.weixin.sdk.api.ApiConfig;
import com.jfinal.weixin.sdk.api.ApiConfigKit;
import com.jfinal.weixin.sdk.jfinal.MsgController;
import com.jfinal.weixin.sdk.kit.MsgEncryptKit;
import com.jfinal.weixin.sdk.msg.InMsgParser;
import com.jfinal.weixin.sdk.msg.OutMsgXmlBuilder;
import com.jfinal.weixin.sdk.msg.in.InMsg;
import com.jfinal.weixin.sdk.msg.in.InTextMsg;
import com.jfinal.weixin.sdk.msg.in.event.InFollowEvent;
import com.jfinal.weixin.sdk.msg.out.OutMsg;
import com.jfinal.weixin.sdk.msg.out.OutTextMsg;

/**
 * 微信消息服务处理
 * @author xkjava
 *
 */
public class WechatMsgController extends Controller{
	
	
	private static final Logger log =  Logger.getLogger(WechatMsgController.class);
	
	private static InMsg inMsg = null;
	private static String inMsgXml = null;
	
	/**
	 * 消息入口
	 * 
	 * 加载WechatMsgInterceptor拦截器,在处理index之前 绑定ApiConfig
	 */
	@Before(WechatMsgInterceptor.class)
	public void index(){
		
		
	}

	
	/**
	 * 此方法在拦截器调用,根据 wechatConfig.txt 配置文件消息 封装 ApiConfig对象,
	 * ApiConfig对象封装了 微信的token appid等信息,有兴趣的同学可以去看下源码
	 * 拦截器内调用此方法返回ApiConfig对象后将次对象绑定在当前线程,这样方便后面具体业务上的调用
	 * 关于线程部分的处理,可以去看源码。如有问题,可以留言,我会根据大家的问题再来做具体介绍。
	 * 当然大神们是不需要的
	 * @return
	 */
	public ApiConfig getApiConfig(){
		ApiConfig apiConfig = new ApiConfig();
		apiConfig.setToken(PropKit.get("token"));
		apiConfig.setAppId(PropKit.get("appId"));
		apiConfig.setAppSecret(PropKit.get("appSecret"));
		/**
		 *  是否对消息进行加密,对应于微信平台的消息加解密方式:
		 *  1:true进行加密且必须配置 encodingAesKey
		 *  2:false采用明文模式,同时也支持混合模式
		 *  
		 *  这里暂时不对消息加解密做处理
		 */
		/*apiConfig.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
		apiConfig.setEncodingAesKey(PropKit.get("encodingAesKey", "setting it in config file"));*/
		return apiConfig;
	}
	
    
	/**
	 * ******************************************消息接收响应转换处理******************************************
	 */
	
	@Before(NotAction.class)
	public InMsg getInMsg() {
		if (inMsg == null)
			inMsg = InMsgParser.parse(getInMsgXml()); 
		return inMsg;
	}
	
	
	/**
	 * 解析接收xml
	 * @return
	 */
	public String getInMsgXml() {
		if(inMsgXml == null)
			inMsgXml = HttpKit.readIncommingRequestData(getRequest());
		
		// 是否需要解密消息
		if (ApiConfigKit.getApiConfig().isEncryptMessage()) {
			inMsgXml = MsgEncryptKit.decrypt(inMsgXml, getRequest().getParameter("timestamp"), getRequest().getParameter("nonce"), getRequest().getParameter("msg_signature"));
		}
		
		log.info("接收消息:\n"+inMsgXml);
		return inMsgXml;
	}
	
	/**
	 * 在接收到微信服务器的 InMsg 消息后后响应 OutMsg 消息
	 */
	public void render(OutMsg outMsg) {
		String outMsgXml = OutMsgXmlBuilder.build(outMsg);
		// 开发模式向控制台输出即将发送的 OutMsg 消息的 xml 内容
		if (ApiConfigKit.isDevMode()) {
			log.info("发送消息:");
			log.info(outMsgXml);
			log.info("--------------------------------------------------------------------------------\n");
		}
		// 是否需要加密消息
		if (ApiConfigKit.getApiConfig().isEncryptMessage()) {
			outMsgXml = MsgEncryptKit.encrypt(outMsgXml, getRequest().getParameter("timestamp"), getRequest().getParameter("nonce"));
		}
		renderText(outMsgXml, "text/xml");
	}

仔细看 getInMsgXml 方法 是用于 解析接收的xml,至于解析的过程 sdk中已经封装好,无需关系,喜欢的可以看看波老师的源码。 render 方法是用户消息的响应。同理,部分内容sdk中已经封装完毕。大家可根据源码看处理过程。


接下来做用户关注 响应,及文本消息处理,在controller中添加以下代码:

/**
	 * 普通关注
	 * InFollowEvent 属于jfianl-weixin 内置对象,需要了解的即可看源码
	 * @param inFollowEvent
	 * @return
	 */
	public void processInFollowEvent(InFollowEvent inFollowEvent){
		if (InFollowEvent.EVENT_INFOLLOW_SUBSCRIBE.equals(inFollowEvent.getEvent())){
			log.info("无参数二维码 关注:openId:{" + inFollowEvent.getFromUserName() + ",原始ID:"+inFollowEvent.getToUserName()+ "}");
			//默认回复
			String resultMsg = "你好,感谢您的关注!";
			OutTextMsg outMsg = new OutTextMsg(inFollowEvent);
			outMsg.setContent(resultMsg);
			render(outMsg);
		}
		
		// 如果为取消关注事件,将无法接收到传回的信息
		if (InFollowEvent.EVENT_INFOLLOW_UNSUBSCRIBE.equals(inFollowEvent.getEvent())){
		}
		return null;
	}
	
	/**
	 * 接收文本消息
	 * @param inTextMsg
	 * @return
	 */
	public void processInTextMsg(InTextMsg inTextMsg)
	{
		
		log.info("接收文本内容:" + inTextMsg.getContent());
		//转发给多客服PC客户端  此处为了客服定位微信用户openid,可以将 用户openId信息重新封装到OutCustomMsg对象转发到客服
		/*OutCustomMsg outCustomMsg = new OutCustomMsg(inTextMsg);
		render(outCustomMsg);*/
		/**
		 * 这里根据用户所发的文本消息做对应业务处理  这里暂时先统一返回文本处理消息
		 */
		OutTextMsg msg = new OutTextMsg(inTextMsg);
		msg.setContent("你好,请问有什么可以帮您。");
		render(msg);
	}

这里的关注 和 文本消息所传入的 对象 也是基于sdk之中的,不同的消息类型都有对应的对象处理,大家还是需要去看看源码,哈哈是不是很sou ez 啊,波老师不愧是波老师啊,至于对应的消息具体怎么处理,大家可根据需求自己更改。(音频,视频,地理位置等消息处理在源码中都可以都有哦!!!)

好了,这个时候我们需要改下我们index 方法了,也就是我们入口啦

/**
	 * 消息入口
	 * 
	 * 加载WechatMsgInterceptor拦截器,在处理index之前 绑定ApiConfig
	 */
	@Before(WechatMsgInterceptor.class)
	public void index(){
		String inMsgXml = null;
		System.out.println("接收消息:");
		System.out.println(getInMsgXml(inMsgXml));
		
		// 解析消息并根据消息类型分发到相应的处理方法
		InMsg msg = InMsgParser.parse(inMsgXml); 
		if (msg instanceof InFollowEvent)
			processInFollowEvent((InFollowEvent) msg); //普通关注
		else if(msg instanceof InTextMsg)
			processInTextMsg((InTextMsg) msg); //文本消息
		
	}

这里解释下,根据传入消息的类型,去做对应的处理,我这里只做了关注和文本消息的处理,需要更多方案的大神们可以继续添加,还是那句话,源码中都有。

基本上就完毕了,现在整个消息服务的类是这样的

package com.jfinal.wechat.config;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.ext.interceptor.NotAction;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Logger;
import com.jfinal.wechat.interceptor.WechatMsgInterceptor;
import com.jfinal.weixin.sdk.api.ApiConfig;
import com.jfinal.weixin.sdk.api.ApiConfigKit;
import com.jfinal.weixin.sdk.jfinal.MsgController;
import com.jfinal.weixin.sdk.kit.MsgEncryptKit;
import com.jfinal.weixin.sdk.msg.InMsgParser;
import com.jfinal.weixin.sdk.msg.OutMsgXmlBuilder;
import com.jfinal.weixin.sdk.msg.in.InMsg;
import com.jfinal.weixin.sdk.msg.in.InTextMsg;
import com.jfinal.weixin.sdk.msg.in.event.InFollowEvent;
import com.jfinal.weixin.sdk.msg.out.OutMsg;
import com.jfinal.weixin.sdk.msg.out.OutTextMsg;

/**
 * 微信消息服务处理
 * @author xkjava
 *
 */
public class WechatMsgController extends Controller{
	
	
	private static final Logger log =  Logger.getLogger(WechatMsgController.class);
	private static InMsg inMsg = null;
	private static String inMsgXml = null;
	
	/**
	 * 消息入口
	 * 
	 * 加载WechatMsgInterceptor拦截器,在处理index之前 绑定ApiConfig
	 */
	@Before(WechatMsgInterceptor.class)
	public void index(){
		
		// 解析消息并根据消息类型分发到相应的处理方法
		InMsg msg = getInMsg();
		if (msg instanceof InFollowEvent)
			processInFollowEvent((InFollowEvent) msg); //普通关注
		else if(msg instanceof InTextMsg)
			processInTextMsg((InTextMsg) msg); //文本消息
		else
			log.error("未能识别的消息类型。 消息 xml 内容为:\n" +  getInMsgXml());
		
	}

	
	/**
	 * 此方法在拦截器调用,根据 wechatConfig.txt 配置文件消息 封装 ApiConfig对象,
	 * ApiConfig对象封装了 微信的token appid等信息,有兴趣的同学可以去看下源码
	 * 拦截器内调用此方法返回ApiConfig对象后将次对象绑定在当前线程,这样方便后面具体业务上的调用
	 * 关于线程部分的处理,可以去看源码。如有问题,可以留言,我会根据大家的问题再来做具体介绍。
	 * 当然大神们是不需要的
	 * @return
	 */
	public ApiConfig getApiConfig(){
		ApiConfig apiConfig = new ApiConfig();
		apiConfig.setToken(PropKit.get("token"));
		apiConfig.setAppId(PropKit.get("appId"));
		apiConfig.setAppSecret(PropKit.get("appSecret"));
		/**
		 *  是否对消息进行加密,对应于微信平台的消息加解密方式:
		 *  1:true进行加密且必须配置 encodingAesKey
		 *  2:false采用明文模式,同时也支持混合模式
		 *  
		 *  这里暂时不对消息加解密做处理
		 */
		/*apiConfig.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
		apiConfig.setEncodingAesKey(PropKit.get("encodingAesKey", "setting it in config file"));*/
		return apiConfig;
	}
	
	
	/**
	 * 普通关注
	 * InFollowEvent 属于jfianl-weixin 内置对象,需要了解的即可看源码
	 * @param inFollowEvent
	 * @return
	 */
	public void processInFollowEvent(InFollowEvent inFollowEvent){
		if (InFollowEvent.EVENT_INFOLLOW_SUBSCRIBE.equals(inFollowEvent.getEvent())){
			log.info("无参数二维码 关注:openId:{" + inFollowEvent.getFromUserName() + ",原始ID:"+inFollowEvent.getToUserName()+ "}");
			//默认回复
			String resultMsg = "你好,感谢您的关注!";
			OutTextMsg outMsg = new OutTextMsg(inFollowEvent);
			outMsg.setContent(resultMsg);
			render(outMsg);
		}
		
		// 如果为取消关注事件,将无法接收到传回的信息
		if (InFollowEvent.EVENT_INFOLLOW_UNSUBSCRIBE.equals(inFollowEvent.getEvent())){
		}
		
	}
	
	/**
	 * 接收文本消息
	 * @param inTextMsg
	 * @return
	 */
	public void processInTextMsg(InTextMsg inTextMsg)
	{
		
		log.info("接收文本内容:" + inTextMsg.getContent());
		//转发给多客服PC客户端  此处为了客服定位微信用户openid,可以将 用户openId信息重新封装到OutCustomMsg对象转发到客服
		/*OutCustomMsg outCustomMsg = new OutCustomMsg(inTextMsg);
		render(outCustomMsg);*/
		/**
		 * 这里根据用户所发的文本消息做对应业务处理  这里暂时先统一返回文本处理消息
		 */
		OutTextMsg msg = new OutTextMsg(inTextMsg);
		msg.setContent("你好,请问有什么可以帮您。");
		render(msg);
	}
	
	
	
	
	
	/**
	 * ******************************************消息接收响应转换处理******************************************
	 */
	
	@Before(NotAction.class)
	public InMsg getInMsg() {
		if (inMsg == null)
			inMsg = InMsgParser.parse(getInMsgXml()); 
		return inMsg;
	}
	
	
	/**
	 * 解析接收xml
	 * @return
	 */
	public String getInMsgXml() {
		if(inMsgXml == null)
			inMsgXml = HttpKit.readIncommingRequestData(getRequest());
		
		// 是否需要解密消息
		if (ApiConfigKit.getApiConfig().isEncryptMessage()) {
			inMsgXml = MsgEncryptKit.decrypt(inMsgXml, getRequest().getParameter("timestamp"), getRequest().getParameter("nonce"), getRequest().getParameter("msg_signature"));
		}
		
		log.info("接收消息:\n"+inMsgXml);
		return inMsgXml;
	}
	
	/**
	 * 在接收到微信服务器的 InMsg 消息后后响应 OutMsg 消息
	 */
	public void render(OutMsg outMsg) {
		String outMsgXml = OutMsgXmlBuilder.build(outMsg);
		// 开发模式向控制台输出即将发送的 OutMsg 消息的 xml 内容
		if (ApiConfigKit.isDevMode()) {
			log.info("发送消息:");
			log.info(outMsgXml);
			log.info("--------------------------------------------------------------------------------\n");
		}
		// 是否需要加密消息
		if (ApiConfigKit.getApiConfig().isEncryptMessage()) {
			outMsgXml = MsgEncryptKit.encrypt(outMsgXml, getRequest().getParameter("timestamp"), getRequest().getParameter("nonce"));
		}
		renderText(outMsgXml, "text/xml");
	}
	

}

还有很重要的一点,在JfinalWechatConfig类中添加路由

    public void configRoute(Routes me) {
		// TODO Auto-generated method stub
		me.add("/msg", WechatMsgController.class);
		
    }

    

ok。这样就好了,我这里是使用的jetty服务,关于jfianl使用tomcat总是出现各种问题,所以选择jetty,启动服务。本地调试输入 http://localhost:端口/项目名/msg

出现  签名验证失败,请确定是微信服务器在发送消息过来即可成功。

接下来我们需要发布到服务器上,然后通过关注对应的公众号测试即可。

这里我使用的百度云 应用引擎 创建一个java-jetty服务 做的测试,价格便宜,做一些测试很划算。如果大家对线上测试这一块还不太了解的话,可以留言,我可以通过一篇博客和大家说明。

(以上全部基于 jfianl-weixin sdk 源码讲解,新手第一次发博客,哪里写的不好或者乱写了,希望大家批评指出。也希望大家仔细看文字说明。)



转载于:https://my.oschina.net/xkjava/blog/539777

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值