java开发微信公众号接受并回复消息[工程代码+图片全解]

写这篇博客时犹豫了好久,因为步骤太多了,上班了也没时间,但是我依然记得当时实现公众号自动回复时的场景,找个案例好

难,也没有一个完整的案例,想了想还是写出来吧,希望能让实现这功能的人少走弯路。

微信公众号平台也有自定义回复消息,比如我在公众号里发送关注你,我们在微信公众号平台设置关键字关注你(就是

有人发送这个关键字就要回复什么内容)设置成回复:**你好,java!**适用于这种固定信息,如果我发送 获取个人信息、我的积

分这种内容就需要动态的数据了,所以要使用我们自己的接口往数据库中进行查询信息。

这个项目实现了简单的回复文字消息,没有 图片、音频等类型的发送、推荐看微信API文档实现,我这也有实现的案例需要的可加我QQ 930496909

首先:

先整理一下大致流程

1.编写java代码,要按照微信公众号提供的API文档来做。

2.下载ngrok工具,假设编写的Java都不会部署到网上(本地运行项目),那我们要想微信能访问我们的java接口我们需要一个工

具(就是将我们本地电脑变成服务器,让别人能来访问我们本地运行的项目说的比较通俗具体可百度~),如果编写的java程序

部署到服务器上就不用啦。

3.在微信公众号平台注册服务号或者订阅号[两者的区别在于服务号收钱功能多,其他区别可自行百度~]我注册的是订阅号,然

后在微信平台进行一些配置,(其实就是让关注公众号的人发送消息后能够对接我们的java接口)

4.进行测试。(我会把源码贴到码云上,可以下载源码https://gitee.com/it_qin/weixintest.git)

接下来就是步骤了。

看一下java结构目录
java开发微信公众号接受并回复消息[工程代码+图片全解]_第1张图片
jar包(因为当时在学校做的还不太会用MAVEN管理,无奈啊,jar包主要就是ssm框架jar包和微信的几个包,我把截图发下,上面

我提供的码云链接上也有jar包)
java开发微信公众号接受并回复消息[工程代码+图片全解]_第2张图片
下面就是每个文件了

web.xml



	 
  
    encodingFilter
    
	        org.springframework.web.filter.CharacterEncodingFilter
    
    
      encoding
      UTF-8
    
    
      forceEncoding
      true
    
  
  
    encodingFilter
    /*  

  
    log4jConfigLocation
    classpath:log4j.properties
   
	  
	    
		org.springframework.web.util.Log4jConfigListener
    
  
  
  
  
  	springMvc
  	org.springframework.web.servlet.DispatcherServlet
  	
  			contextConfigLocation
  			classpath:springmvc-servlet.xml
  	
  	1
  
  
  
  	springMvc
  	*.do
  
  
  
  
  	contextConfigLocation
  	classpath:applicationContext-mybatis.xml
   
  
  
  	org.springframework.web.context.ContextLoaderListener
  


springmvc-servlet.xml



        
   
   
   
   		
   			
   				
   					
   						application/json;charset=UTF-8
   					
   				
   			
   			
   				
   					
   						text/html;charset=UTF-8
   						application/json
   					
   				
   				
   					
   						WriteDateUseDateFormat
   					
   				
   			
   		
   
    
    
         
         
        
            
            	
                
                
            
        
        
            
                
				   
				   
			   
            
        
    
 
	
 	
	 
	
	
		
		
	 
   

applicationContext-mybatis.xml




	
	
	
	
	
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
	

	
	
		
	

	
	
		
		
	

	
	
		
		
	

	
		
			
			
			
			
			
		
	
	
		
	
	

mybatis-config.xml

  
  
  
       
           
           
       
       
          
         
      
  

database.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/ktvsystem?useUnicode=true&characterEncoding=utf-8
user=root
password=admin
minIdle=45
maxIdle=50
initialSize=5
maxActive=100
maxWait=100
removeAbandonedTimeout=240
removeAbandoned=true

log4j.properties

log4j.rootLogger=debug,CONSOLE,file
#log4j.rootLogger=ERROR,ROLLING_FILE

log4j.logger.cn.smbms=debug
log4j.logger.org.apache.ibatis=debug
log4j.logger.org.mybatis.spring=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug

######################################################################################
# Console Appender  \u65e5\u5fd7\u5728\u63a7\u5236\u8f93\u51fa\u914d\u7f6e
######################################################################################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=debug
log4j.appender.CONSOLE.DatePattern=yyyy-MM-dd
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern= - (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n



######################################################################################
# Rolling File  \u6587\u4ef6\u5927\u5c0f\u5230\u8fbe\u6307\u5b9a\u5c3a\u5bf8\u7684\u65f6\u5019\u4ea7\u751f\u4e00\u4e2a\u65b0\u7684\u6587\u4ef6
######################################################################################
#log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
#log4j.appender.ROLLING_FILE.Threshold=INFO
#log4j.appender.ROLLING_FILE.File=${baojia.root}/logs/log.log
#log4j.appender.ROLLING_FILE.Append=true
#log4j.appender.ROLLING_FILE.MaxFileSize=5000KB
#log4j.appender.ROLLING_FILE.MaxBackupIndex=100
#log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
#log4j.appender.ROLLING_FILE.layout.ConversionPattern=%d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n

######################################################################################
# DailyRolling File  \u6bcf\u5929\u4ea7\u751f\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6\uff0c\u6587\u4ef6\u540d\u683c\u5f0f:log2009-09-11
######################################################################################
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern=yyyy-MM-dd
log4j.appender.file.File=${AppInfoSystem.root}/logs/log.log
log4j.appender.file.Append=true
log4j.appender.file.Threshold=debug
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern= - (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n

#DWR \u65e5\u5fd7
#log4j.logger.org.directwebremoting = ERROR

#\u663e\u793aHibernate\u5360\u4f4d\u7b26\u7ed1\u5b9a\u503c\u53ca\u8fd4\u56de\u503c
#log4j.logger.org.hibernate.type=DEBUG,CONSOLE 

#log4j.logger.org.springframework.transaction=DEBUG
#log4j.logger.org.hibernate=DEBUG
#log4j.logger.org.acegisecurity=DEBUG
#log4j.logger.org.apache.myfaces=TRACE
#log4j.logger.org.quartz=DEBUG

#log4j.logger.com.opensymphony=INFO  
#log4j.logger.org.apache.struts2=DEBUG  
log4j.logger.com.opensymphony.xwork2=debug

WeiXinController.java

package com.qhk.controller;

import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.qhk.util.CheckUtil;
import com.qhk.util.MessageFormat;
import com.qhk.util.MessageUtil;

@Controller
@RequestMapping("/weixin")
public class WeiXinController {
	/**
	 * 

功能:[微信验证 ][2018年2月9日 下午10:01:14][创建人: HongKun.Qin]

*

* @param request * @param response * @return */ @ResponseBody @RequestMapping(value = "/message.do",method =RequestMethod.GET) public String getMessageValidate(HttpServletRequest request, HttpServletResponse response){ String signature = request.getParameter("signature");//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 String timestamp = request.getParameter("timestamp");// 时间戳 String nonce = request.getParameter("nonce");// 随机数 String echostr = request.getParameter("echostr");// 随机字符串 if(CheckUtil.checkSignature(signature, timestamp, nonce)){ return echostr; } return ""; } /** *

功能:[接受消息,并返回消息 ][2018年2月9日 下午10:02:00][创建人: HongKun.Qin]

*

* @param request * @param response * @return * @throws Exception */ @ResponseBody @RequestMapping(value = "/message.do",method =RequestMethod.POST) public String getMessage(HttpServletRequest request, HttpServletResponse response) throws Exception{ Map map = new MessageFormat().xmlToMap(request); String fromUserName = map.get("FromUserName");//公众号 String toUserName = map.get("ToUserName");//粉丝号 String msgType = map.get("MsgType");//发送的消息类型[比如 文字,图片,语音。。。] String content = map.get("Content");//发送的消息内容 String message = null; System.out.println("fromUserName:"+fromUserName+" ToUserName:"+toUserName+" MsgType:"+msgType+" "+content); //判断发送的类型是文本 if(MessageUtil.MESSAGE_TEXT.equals(msgType)){ //发送的内容为???时 if("0".equals(content)){ message = MessageFormat.initText(toUserName, fromUserName, MessageUtil.menuText()); }else if("1".equals(content)) { Random random = new Random(); message = MessageFormat.initText(toUserName, fromUserName, String.format("您本次的验证码为:%s%s%s%s", random.nextInt(10),random.nextInt(10),random.nextInt(10),random.nextInt(10)));//模拟验证码 }else{ message = MessageFormat.initText(toUserName, fromUserName, "功能正在完善中,请按提示信息操作[回复'0'显示主菜单]。"); } }else if(MessageUtil.MESSAGE_EVENT.equals(msgType)){//验证是关注/取消事件 String eventType = map.get("Event");//获取是关注还是取消 //关注 if(MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)){ message = MessageFormat.initText(toUserName, fromUserName, "欢迎关注青鸟ktv,回复[0]即可调出功能菜单"); } } return message; } }

AccessToken.java

package com.qhk.entity;

public class AccessToken {

	private String token;
	private int expiresIn;
	
	public String getToken() {
		return token;
	}
	public void setToken(String token) {
		this.token = token;
	}
	public int getExpiresIn() {
		return expiresIn;
	}
	public void setExpiresIn(int expiresIn) {
		this.expiresIn = expiresIn;
	}
}

BaseMessage.java

package com.qhk.entity;

public class BaseMessage {
	private String ToUserName;
	private String FromUserName;
	private long CreateTime;
	private String MsgType;
	public String getToUserName() {
		return ToUserName;
	}
	public void setToUserName(String toUserName) {
		ToUserName = toUserName;
	}
	public String getFromUserName() {
		return FromUserName;
	}
	public void setFromUserName(String fromUserName) {
		FromUserName = fromUserName;
	}
	public long getCreateTime() {
		return CreateTime;
	}
	public void setCreateTime(long createTime) {
		CreateTime = createTime;
	}
	public String getMsgType() {
		return MsgType;
	}
	public void setMsgType(String msgType) {
		MsgType = msgType;
	}
}

TextMessage.java

package com.qhk.entity;

public class TextMessage extends BaseMessage{

	private String Content;
	private String MsgId;
	
	public String getContent() {
		return Content;
	}
	public void setContent(String content) {
		Content = content;
	}
	public String getMsgId() {
		return MsgId;
	}
	public void setMsgId(String msgId) {
		MsgId = msgId;
	}
}

CheckUtil.java(token注意,我现在是qhk后面微信公众号平台配置也要用这个,自己改了的话就填自己改的)

package com.qhk.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class CheckUtil {
	public static final String token = "qhk";//这个地方也要注意
	public static boolean checkSignature(String signature,String timestamp,String nonce){
		String[] arr=new String[]{token,timestamp,nonce};
		//排序
		Arrays.sort(arr);
		//生成字符串
		StringBuffer content = new StringBuffer();
		for (int i = 0; i < arr.length; i++) {
			content.append(arr[i]);
		}
		//sha1加密
		String temp = getSha1(content.toString());
		return temp.equals(signature);
	}
	public static String getSha1(String str){
		if (null == str || 0 == str.length()){
			return null;
		}
		char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
				'a', 'b', 'c', 'd', 'e', 'f'};
		try {
			MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
			mdTemp.update(str.getBytes("UTF-8"));

			byte[] md = mdTemp.digest();
			int j = md.length;
			char[] buf = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
				buf[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(buf);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

}

MessageFormat.java

package com.qhk.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.qhk.entity.TextMessage;
import com.thoughtworks.xstream.XStream;

/**
 * 

将发送的消息进行转换

* @author HongKun.Qin */ public class MessageFormat { /** * xml 转 map * * @param request * @return * @throws IOException * @throws DocumentException */ public static Map xmlToMap(HttpServletRequest request) throws IOException, DocumentException { Map map = new HashMap(); SAXReader reader = new SAXReader(); InputStream ins = request.getInputStream(); Document doc = reader.read(ins); Element root = doc.getRootElement(); List list = root.elements(); for (Element e : list) { map.put(e.getName(), e.getText()); } ins.close(); return map; } /** * 将文本消息转换为xml * * @param textMessage * @return */ public static String textMessageToXml(TextMessage textMessage) { XStream xStream = new XStream(); xStream.alias("xml", textMessage.getClass()); return xStream.toXML(textMessage); } public static String initText(String toUserName, String fromUserName, String content) { TextMessage text = new TextMessage(); text.setFromUserName(toUserName); text.setToUserName(fromUserName); text.setMsgType(MessageUtil.MESSAGE_TEXT); text.setCreateTime(new Date().getTime()); text.setContent(content); return textMessageToXml(text); } }

MessageUtil.java

package com.qhk.util;

public class MessageUtil {
	/**
	 * 类型
	 */
	public static final String MESSAGE_TEXT = "text";//文本
	public static final String MESSAGE_NEWS = "news";
	public static final String MESSAGE_IMAGE = "image";
	public static final String MESSAGE_MUSIC = "music";
	public static final String MESSAGE_VOICE = "voice";
	public static final String MESSAGE_VIDEO = "video";
	public static final String MESSAGE_LINK = "link";
	public static final String MESSAGE_LOCATION = "location";
	public static final String MESSAGE_EVENT = "event";
	public static final String MESSAGE_SUBSCRIBE = "subscribe";
	public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";
	public static final String MESSAGE_CLICK = "CLICK";
	public static final String MESSAGE_VIEW = "VIEW";
	public static final String MESSAGE_SCANCODE = "scancode_push";

	
	/**
	 * 

功能:[显示的主菜单 ][2018年2月9日 下午9:37:56][创建人: HongKun.Qin]

*

* @return */ public static String menuText() { StringBuffer sb = new StringBuffer(); sb.append("欢迎您关注青鸟KTV,请按照菜单提示进行操作:\n\n"); sb.append("[1].显示短信验证码\n"); sb.append("[2].显示个人信息\n"); sb.append("[3].关于青鸟KTV\n"); sb.append("[4].关于注册成为会员\n\n"); sb.append("回复 \"[0]\" 调出此菜单。"); return sb.toString(); } }

WeixinUtil.java(APPID、APPSECRET)别忘改成自己的,不然项目也没法运行

package com.qhk.util;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.qhk.entity.AccessToken;

import net.sf.json.JSONObject;


public class WeixinUtil {

	private static final String APPID="";//在基础配置中可查看自己APPID
	private static final String APPSECRET="";//在基础配置中可查看自己APPSECRET
	private static final String ACCESS_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	private static final String UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
	public static JSONObject doGetStr(String url){
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpGet httpGet=new HttpGet(url); 
		JSONObject jsonObject = null;
		try {
			HttpResponse response=httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			if(entity!=null){
				String result = EntityUtils.toString(entity,"UTF-8");
				jsonObject = JSONObject.fromObject(result);
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println(jsonObject);
		return jsonObject;
	}
	/**
	 * 
	 * @Description: TODO 获取AccessToken
	 * @param @return   
	 * @return AccessToken  
	 * @throws
	 * @author qinhongkun
	 * @date 2017-12-18
	 */
	public static AccessToken getAccessToken(){
		AccessToken token = new AccessToken();
		String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
		JSONObject jsonObject = doGetStr(url);
		if(jsonObject!=null){
			token.setToken(jsonObject.getString("access_token"));
			token.setExpiresIn(jsonObject.getInt("expires_in"));
		}
		return token;
	}
	
	/*
	 * 文件上传
	 */
	public static String upload(String filePath, String accessToken,String type) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
		System.out.println("filePath:"+filePath);
		File file = new File(filePath);
		if (!file.exists() || !file.isFile()) {
			throw new IOException("文件不存在");
		}

		String url = UPLOAD_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE",type);
		
		URL urlObj = new URL(url);
		//连接
		HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();

		con.setRequestMethod("POST"); 
		con.setDoInput(true);
		con.setDoOutput(true);
		con.setUseCaches(false); 

		//设置请求头信息
		con.setRequestProperty("Connection", "Keep-Alive");
		con.setRequestProperty("Charset", "UTF-8");

		//设置边界
		String BOUNDARY = "----------" + System.currentTimeMillis();
		con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

		StringBuilder sb = new StringBuilder();
		sb.append("--");
		sb.append(BOUNDARY);
		sb.append("\r\n");
		sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n");
		sb.append("Content-Type:application/octet-stream\r\n\r\n");

		byte[] head = sb.toString().getBytes("utf-8");

		//获得输出流
		OutputStream out = new DataOutputStream(con.getOutputStream());
		//输出表头
		out.write(head);

		//文件正文部分
		//把文件已流文件的方式 推入到url中
		DataInputStream in = new DataInputStream(new FileInputStream(file));
		int bytes = 0;
		byte[] bufferOut = new byte[1024];
		while ((bytes = in.read(bufferOut)) != -1) {
			out.write(bufferOut, 0, bytes);
		}
		in.close();

		//结尾部分
		byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");//定义最后数据分隔线

		out.write(foot);

		out.flush();
		out.close();

		StringBuffer buffer = new StringBuffer();
		BufferedReader reader = null;
		String result = null;
		try {
			//定义BufferedReader输入流来读取URL的响应
			reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
				buffer.append(line);
			}
			if (result == null) {
				result = buffer.toString();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				reader.close();
			}
		}

		JSONObject jsonObj = JSONObject.fromObject(result);
		System.out.println(jsonObj);
		String typeName = "media_id";
		if(!"image".equals(type)){
			typeName = type + "_media_id";
		}
		String mediaId = jsonObj.getString(typeName);
		return mediaId;
	}
	
}

2.大家现在就是关心ngrok下载地址:https://ngrok.com/download

还有人会问:哎哟我靠,什么是ngrok?

其实不用纠结这是个啥,如果你作为一个Java开发人员是第一次接触微信公众号后台开发,我建议你千万别纠结这到底是个

啥,简单明了的告诉你:微信公众号开发文档中 要求 有服务器 (自己的域名、也可以理解为自己的空间 当然 不是QQ空

间),然后呢,那你就想百度一下了,怎么拥有自己的域名或者说空间,有人推荐你使用百度BEA(好像是,不知道名字有

没有记错),然后微信公众号的技术文档里面推荐你用腾讯的什么什么,总之,收费。诶,对 就是收费。

所以呢,这个ngrok就是免费的。而且运行极其简单,对,不费劲哈。

这个下载之后,暂时放那,别动。

3.注册订阅号 去微信公众号平台注册一个个人的订阅号就行,登录进去,三个箭头分别点击一下将最下面红箭头标出的地方进

行关闭
java开发微信公众号接受并回复消息[工程代码+图片全解]_第3张图片
关闭后
java开发微信公众号接受并回复消息[工程代码+图片全解]_第4张图片
看图操作
java开发微信公众号接受并回复消息[工程代码+图片全解]_第5张图片java开发微信公众号接受并回复消息[工程代码+图片全解]_第6张图片java开发微信公众号接受并回复消息[工程代码+图片全解]_第7张图片
此时 我们还需要配置下图

配置你的服务器地址 (这是问题1)

配置你的token (这是问题2)

配置你的EncodingAESkey (这不是问题!!)
java开发微信公众号接受并回复消息[工程代码+图片全解]_第8张图片
问题1:

然后你肯定进入了死胡同,想说URL怎么填呢?

你还记得你的ngrok吗?

首先我们先在本地启动项目,(注意代码中需要修改的地方上面我已经写出来,填写自己的APPID和密码)必须是tomcat的8080

端口

这时候就要用到ngrok了

打开你的ngrok文件夹,在包涵ngrok.exe文件的文件夹中运行cmd,然后输入指令:

ngrok -config ngrok.cfg -subdomain qinhongkun 8080

qinhongkun可以随便改,自己填写服务器地址别写错了就行。
java开发微信公众号接受并回复消息[工程代码+图片全解]_第9张图片

如果没有什么问题的话下面这张图就是启动成功的(别关掉这dos窗口)
java开发微信公众号接受并回复消息[工程代码+图片全解]_第10张图片
转回来微信公众号,你的URL就填写ngrok运行后的生成的网址(我已经用红色标记出来了用哪一个都行有两个)/项目名称/控

制器名 比如我的就是 https://qinhongkun.tunnel.echomod.cn/weixintest/weixin/message.do

至于为什么我的项目名是weixintest而不是weixin-demo 那是我之前在eclipse中改了项目名,而tomcat中没有修改过来,

weixin/message.do这控制器方法上面有。

问题2:

token 就要填我们在项目中写的那个,上面我也重点标记了,如果项目中更改了的话,这别忘了修改!

问题3:直接点击随机生成一个就ok了

如果没有问题现在已经能保存了。

我将项目上传到码云,https://gitee.com/it_qin/weixintest.git。

注:因为当时用作项目中有很多功能,所以这是个完整的ssm框架,只不过我把那些都删了,只留下一个简单的微信Demo.

现在去你的公众号测试一下就行了,有什么问题或者建议欢迎评论,确保一天之内回复,不算星期天哦。

你可能感兴趣的:(微信公众号开发)