转载请标明出处,谢谢!
版本说明:
V1:
2014-3-30 版
前言:
因为要进行微信开发,就必须要成为微信开发者,要想成为微信开发者,就必须要有服务器响应微信的 Token 验证,如果没有公网服务器环境,可以去了解下BAE、SAE或阿里云,这里以 BAE 为例。
前提条件:
(1)拥有微信公众平台帐号(申请地址:https://mp.weixin.qq.com/)
(2)拥有百度BAE开发者帐号(申请地址:http://developer.baidu.com/)
(3)搭建好 Java 开发环境,没有搭建好的可参考
Java 开发环境搭建
准备工作:
下载安装 MyEclipse 工具,SVN 代码版本管理工具,SVN 在给百度 BAE 提交 war 包的方法请参考百度开发者文档 SVN 的使用 <
http://developer.baidu.com/wiki/index.php?title=docs/cplat/rt/manage/svn#SVN.E5.AE.A2.E6.88.B7.E7.AB.AF.E4.BD.BF.E7.94.A8.E8.AF.B4.E6.98.8E>
详细步骤:
1、去BAE快速创建一个JAVA应用
去到百度开放云首页 (
http://developer.baidu.com/),点击右上角 “管理控制台” ,进入我的应用页面:如图 1
图 1
点击 “创建应用” 填上应用名称,点击“保存”,如图2
图 2
你就会看到你创建好的应用:(图 3)
图 3
2、添加部署
点击应用图标,查看应用信息,点击“应用引擎” 弹出“部署列表”页面:图 4
图 4
点击“添加部署”,按要求填写, 类型选择 Java-tomcat:图5
如果部署失败并提示警告,由于 bae 升级到 3.0 版本,实行分批制度,看百度网站公告,如果你没有拿到 BEA 资源,就无法继续进行操作。
成功部署后,是这样的:
3、新建项目
打开 MyEclipse ,新建一个 Web Project :
新建一个 servlet 包,方法是:"src" --> 右键 --> new --> packages, 命名随意,例如 org.ivy.course.servlet
通过向导往包里添加一个能够处理请求的Servlet 类,具体操作时包名右键 --> new --> Servlet:
package org.ivy.course.servlet;
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;
public class CoreServlet extends HttpServlet {
/**
* Constructor of the object.
*/
public CoreServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the GET method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
同时,配置文件 web.xml 也会自动添加 < servlet > 和 < servlet - mapping> 两个配置项:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>CoreServlet</servlet-name>
<servlet-class>org.ivy.course.servlet.CoreServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CoreServlet</servlet-name>
<url-pattern>/servlet/CoreServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app
如果你想看看这些代码有什么效果,你可以试着运行工程:run as --> MyEclipse server Appcation,弹出网页:
我们在上图中的网址后面添加 <url-pattern> 中设定的值 /servlet/CoreServlet (见 web.xml 文件)并回车,效果如下:
看到这些网页打印的信息,再对比一下代码,你应该能明白上述示例代码的用处了。
我们按控制台那个红色方框,停止运行工程,回到类 CoreServlet,将 doGet 和 doPost
方法里面的代码删掉,并在 doGet 方法中国添加我们的代码:
// my
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戮
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
PrintWriter out = response.getWriter();
// 通过检验 signature 对请求进行校验,若校验成功则原样返回 echostr,表示接入成功,否则接入失败
if(SignUtil.checkSignature(signature, timestamp, nonce)){
out.print(echostr);
}
out.close();
out = null;
代码中用到了 checkSignature 方法,该方法还没有实现,我们新建一个包 org.ivy.course.util 作为一个工具包,并往该包中添加新类 SignUtil,添加类的方法是:包名右键 -->new --> class,填上类名 SignUtil ,其它默认,完整代码如下:
package org.ivy.course.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class SignUtil {
/**
* 与接口配置信息中的 token 要一致,这里赋予什么值,在接口配置信息中的Token就要填写什么值,
* 两边保持一致即可,建议用项目名称、公司名称缩写等,我在这里用的是项目名称weixinface
*/
private static String token = "weixinface";
/**
* 验证签名
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce){
String[] arr = new String[]{token, timestamp, nonce};
// 将 token, timestamp, nonce 三个参数进行字典排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for(int i = 0; i < arr.length; i++){
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行 shal 加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
content = null;
// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()): false;
}
/**
* 将字节数组转换为十六进制字符串
* @param digest
* @return
*/
private static String byteToStr(byte[] digest) {
// TODO Auto-generated method stub
String strDigest = "";
for(int i = 0; i < digest.length; i++){
strDigest += byteToHexStr(digest[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
* @param b
* @return
*/
private static String byteToHexStr(byte b) {
// TODO Auto-generated method stub
char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] tempArr = new char[2];
tempArr[0] = Digit[(b >>> 4) & 0X0F];
tempArr[1] = Digit[b & 0X0F];
String s = new String(tempArr);
return s;
}
}
最后,看看代码,代码应该不会出错的了,但是,在类名 CoreServlet 上应该有个警告,根据编译器的提示,鼠标移到
CoreServlet 上,根据提示选择 add default serial
Version ID
添加一个默认的
serialVersionUID。
到此,代码的编辑工作完成了,下一步就是打包部署了。
4、打包并提交到百度 BAE
工程右键打包一个 ROOT.war 包,名字必须是这个,保存地址建议保存到工程目录下,具体操作: 工程右键 --> Export --> Java EE --> WAR file,根据提示来操作保存。
到我们的 SVN 工作目录,新建一个文件夹,命名随意,例如 weixin0330,然后在文件夹上右键,选择 SVN CheckOut,填上 URL 地址,该地址可以到百度 BAE 上我们部署的应用中获得。
Checkout 出来默认版本号是 1:
进入CheckOut 的项目中,可以看到目录结构如下:
鼠标选中 ROOT.war 文件,右键 --> TortoiseSVN --> Delect,将该文件删除,删除后,文件夹会有一个感叹号,我们在文件夹 weixin0330 上:右键 --> SVN Commit --> OK,目的是将百度 BAE 上面的 ROOT.war 删除掉:
然后,我们回到 MyEclipse 的工作空间,将我们打包好的 ROOT.war 文件复制到 SVN 的工程目录下,复制进来的 ROOT.war 文件上会有个问号:
我们在文件 ROOT.war 上右键 --> TortoiseSVN --> add,此时问号变成加号,然后
在文件夹 weixin0330 上:右键 --> SVN Commit --> OK,将我们最新的ROOT.war 提交到百度 BAE 。
然后回到百度 BAE 中查看我们的部署列表,会看到提示有“新版本” ,点击快捷发布。
然后点击查看,在弹出网页的网址后面添加web.xml 文件中
<url-pattern> 设定的值“ /servlet/CoreServlet” 并回车,会看到如下页面:
如果你看到了上述 500 画面说明你离成功只差一步了,记住复制此网页的地址备用。
5、
成为微信开发者
打开微信公众平台 -> 高级功能 -> 开发者模式,见图:
将我们刚才复制的地址黏贴到 URL ;
在填写 Token 之前,回到我们的项目,在类 SignUtil 中有这么一句代码:
private static String token = "weixinface";
代码中的 token 的值我们可以随意写,但是,这里是什么值,在微信平台上就要填写对应的内容,所有,在 Token 那里填上 weixinface,点击“提交”,如果代码没有问题,瞬间你就可以看到“你已成为开发者” 的提示,如图 :
到此,所有的工作都已经完成,你可以不断丰富你的代码,实现不同的功能。你也可以在自己的微信中关注自己的订阅号,只需扫描公众平台的二维码就行了。
欢迎关注我的订阅号:天龙智能
二维码:
郑重声明:
本博客的代码是来自柳老师的
博客
(
http://blog.csdn.net/column/details/wechatmp.html
)我只是作为一种补充,我希望以此方式来表达我对柳老师的感谢之情,完全没有盗版之意,如有侵犯,请联系我,谢谢!