微信公众号Java接入demo
前不久买了一台服务,本来是用来当梯子用的,后来买了一个域名搭了一个博客网站,后来不怎么在上面写博客一直闲着,最近申请了一个微信公众号就想着弄点什么玩玩。周末没事就鼓捣了下微信公众号的接入。
准备工作
一台能用域名访问的服务器
一个微信公众号
给服务器装上jdk、tomcat、ftp、shell工具
编码
登录测试公众号后台,获取appId和appSecret,新建一个配置文件来保存ppId和appSecret,也可以直接写在代码里,个人不建议这么写,在项目中经常会用到一些常量或者说是资源配置,比如要接入其他公司推给你的数据,会给你接口地址、验证码什么的统一建一个配置文件存放会比较好一点,在以后的频繁的修改中就会凸显出重要性,从软件的结构来看也比较清晰。
-新建一个servlet,编写代码,下面图片是微信公众号的基本配置界面,在下图的url 上填写你服务器用来接受微信验证的url,url必须以http://或https://开头,分别支持80端口和443端口。用来接收微信消息和事件接口的urltoken随便填写,加密方式我选择了安全模式,
这里写图片描述
先贴代码,本人文档水平有限:
这是一个servlet文件,用来处理微信发过来的认证请求;
package myservlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class MyServlet
*/
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public MyServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter();
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
boolean isSuccess = CheckUtil.check(signature, timestamp, nonce);
if(isSuccess) {
pw.print(echostr);
pw.write("接入成功!");
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
验证方法
/**
* @Title: CheckUtil.java
* @Package myservlet
* @Description: TODO(用一句话描述该文件做什么)
* @author wjk
* @date 2018年7月5日
* @version V1.0
*/
package myservlet;
import java.util.Arrays;
/**
* @ClassName: CheckUtil
* @Description: TODO(这里用一句话描述这个类的作用)
* @author wjk
* @date 2018年7月5日
*
*/
public class CheckUtil {
public static final String token ="##";
public static boolean check(String signature,String timestamp,String nonce ) {
String arrs[] = {token,timestamp,nonce};
Arrays.sort(arrs);//字典排序
//拼接字符串
StringBuffer sb = new StringBuffer();
for(String str :arrs) {
sb.append(str);
}
String signaturesha1 = Sha1Util.encode(sb.toString());
return signaturesha1.equals(signature);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
sha1加密
package myservlet;
import java.security.MessageDigest;
public final class Sha1Util {
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
'e', 'f' };
/**
*
* @Title: getFormattedText
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @param bytes
* @param @return 参数
* @return String 返回类型
* @throws
*/
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
// 把密文转换成十六进制的字符串形式
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
/**
*
* @Title: encode
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @param str
* @param @return 参数
* @return String 返回类型
* @throws
*/
public static String encode(String str) {
if (str == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(str.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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">
<servlet>
<!--servlet名称,可以自定义-->
<servlet-name>MyServlet</servlet-name>
<!-- servlet类名: 包名+简单类名-->
<servlet-class>myservlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<!--servlet名称,应与上面的名称保持一致,因为是通过下面的servlet访问名称来定位到上面的servlet名称,再通过上面的名称定位到servlet类的位置-->
<servlet-name>MyServlet</servlet-name>
<!-- servlet的访问名称: /名称 -->
<url-pattern>/helloMyServlet.do</url-pattern>
</servlet-mapping>
</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
原理
将token,timestamp,nonce进行字典排序,拼接成一个字符串。
将字符串进行sha1加密。
将加密后的字符创和signature比较。true则提交成功,请原样返回echostr参数内容;false则为失败。