微信公众平台开发之基于百度 BAE3.0 的开发环境搭建(MyEclipse + SVN)

转载请标明出处,谢谢!  
版本说明:
    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

图 5

如果部署失败并提示警告,由于 bae 升级到 3.0 版本,实行分批制度,看百度网站公告,如果你没有拿到 BEA 资源,就无法继续进行操作。

成功部署后,是这样的:



3、新建项目

    打开 MyEclipse ,新建一个 Web Project :



     新建一个 servlet 包,方法是:"src" --> 右键 --> new --> packages, 命名随意,例如 org.ivy.course.servlet

    通过向导往包里添加一个能够处理请求的Servlet 类,具体操作时包名右键 --> new --> Servlet:





    finish 后,就能看到建好的类,并配有示例代码:

[java]  view plain copy
  1. package org.ivy.course.servlet;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5.   
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. public class CoreServlet extends HttpServlet {  
  12.   
  13.     /** 
  14.      * Constructor of the object. 
  15.      */  
  16.     public CoreServlet() {  
  17.         super();  
  18.     }  
  19.   
  20.     /** 
  21.      * Destruction of the servlet. <br> 
  22.      */  
  23.     public void destroy() {  
  24.         super.destroy(); // Just puts "destroy" string in log  
  25.         // Put your code here  
  26.     }  
  27.   
  28.     /** 
  29.      * The doGet method of the servlet. <br> 
  30.      * 
  31.      * This method is called when a form has its tag value method equals to get. 
  32.      *  
  33.      * @param request the request send by the client to the server 
  34.      * @param response the response send by the server to the client 
  35.      * @throws ServletException if an error occurred 
  36.      * @throws IOException if an error occurred 
  37.      */  
  38.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  39.             throws ServletException, IOException {  
  40.   
  41.         response.setContentType("text/html");  
  42.         PrintWriter out = response.getWriter();  
  43.         out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");  
  44.         out.println("<HTML>");  
  45.         out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");  
  46.         out.println("  <BODY>");  
  47.         out.print("    This is ");  
  48.         out.print(this.getClass());  
  49.         out.println(", using the GET method");  
  50.         out.println("  </BODY>");  
  51.         out.println("</HTML>");  
  52.         out.flush();  
  53.         out.close();  
  54.     }  
  55.   
  56.     /** 
  57.      * The doPost method of the servlet. <br> 
  58.      * 
  59.      * This method is called when a form has its tag value method equals to post. 
  60.      *  
  61.      * @param request the request send by the client to the server 
  62.      * @param response the response send by the server to the client 
  63.      * @throws ServletException if an error occurred 
  64.      * @throws IOException if an error occurred 
  65.      */  
  66.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  67.             throws ServletException, IOException {  
  68.   
  69.         response.setContentType("text/html");  
  70.         PrintWriter out = response.getWriter();  
  71.         out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");  
  72.         out.println("<HTML>");  
  73.         out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");  
  74.         out.println("  <BODY>");  
  75.         out.print("    This is ");  
  76.         out.print(this.getClass());  
  77.         out.println(", using the POST method");  
  78.         out.println("  </BODY>");  
  79.         out.println("</HTML>");  
  80.         out.flush();  
  81.         out.close();  
  82.     }  
  83.   
  84.     /** 
  85.      * Initialization of the servlet. <br> 
  86.      * 
  87.      * @throws ServletException if an error occurs 
  88.      */  
  89.     public void init() throws ServletException {  
  90.         // Put your code here  
  91.     }  
  92.   
  93. }  

     同时,配置文件 web.xml 也会自动添加  < servlet > 和 < servlet - mapping> 两个配置项:

[java]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5"   
  3.     xmlns="http://java.sun.com/xml/ns/javaee"   
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  6.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  7.   
  8.   <servlet>  
  9.     <description>This is the description of my J2EE component</description>  
  10.     <display-name>This is the display name of my J2EE component</display-name>  
  11.     <servlet-name>CoreServlet</servlet-name>  
  12.     <servlet-class>org.ivy.course.servlet.CoreServlet</servlet-class>  
  13.   </servlet>  
  14.   
  15.   <servlet-mapping>  
  16.     <servlet-name>CoreServlet</servlet-name>  
  17.     <url-pattern>/servlet/CoreServlet</url-pattern>  
  18.   </servlet-mapping>  
  19.   
  20.   <welcome-file-list>  
  21.     <welcome-file>index.jsp</welcome-file>  
  22.   </welcome-file-list>  
  23. </web-app  

     如果你想看看这些代码有什么效果,你可以试着运行工程:run as --> MyEclipse server Appcation,弹出网页:



    我们在上图中的网址后面添加 <url-pattern> 中设定的值 /servlet/CoreServlet (见 web.xml 文件)并回车,效果如下:



   看到这些网页打印的信息,再对比一下代码,你应该能明白上述示例代码的用处了。

    我们按控制台那个红色方框,停止运行工程,回到类  CoreServlet,将 doGet 和 doPost  方法里面的代码删掉,并在 doGet 方法中国添加我们的代码:

[java]  view plain copy
  1. // my  
  2. // 微信加密签名  
  3. String signature = request.getParameter("signature");  
  4. // 时间戮  
  5. String timestamp = request.getParameter("timestamp");  
  6. // 随机数  
  7. String nonce = request.getParameter("nonce");  
  8. // 随机字符串  
  9. String echostr = request.getParameter("echostr");   
  10.   
  11. PrintWriter out = response.getWriter();  
  12. // 通过检验 signature 对请求进行校验,若校验成功则原样返回 echostr,表示接入成功,否则接入失败  
  13. if(SignUtil.checkSignature(signature, timestamp, nonce)){  
  14.    out.print(echostr);  
  15. }  
  16.   
  17. out.close();  
  18. out = null;   

    代码中用到了 checkSignature 方法,该方法还没有实现,我们新建一个包 org.ivy.course.util 作为一个工具包,并往该包中添加新类 SignUtil,添加类的方法是:包名右键 -->new --> class,填上类名  SignUtil ,其它默认,完整代码如下:

[java]  view plain copy
  1. package org.ivy.course.util;  
  2.   
  3. import java.security.MessageDigest;  
  4. import java.security.NoSuchAlgorithmException;  
  5. import java.util.Arrays;  
  6.   
  7. public class SignUtil {  
  8.        /** 
  9.      * 与接口配置信息中的 token 要一致,这里赋予什么值,在接口配置信息中的Token就要填写什么值, 
  10.      * 两边保持一致即可,建议用项目名称、公司名称缩写等,我在这里用的是项目名称weixinface 
  11.      */  
  12.     private static String token = "weixinface";  
  13.       
  14.     /** 
  15.      * 验证签名 
  16.      * @param signature 
  17.      * @param timestamp 
  18.      * @param nonce 
  19.      * @return 
  20.      */  
  21.     public static boolean checkSignature(String signature, String timestamp, String nonce){  
  22.         String[] arr = new String[]{token, timestamp, nonce};  
  23.         // 将 token, timestamp, nonce 三个参数进行字典排序  
  24.         Arrays.sort(arr);  
  25.         StringBuilder content = new StringBuilder();  
  26.         for(int i = 0; i < arr.length; i++){  
  27.             content.append(arr[i]);  
  28.         }  
  29.         MessageDigest md = null;  
  30.         String tmpStr = null;  
  31.           
  32.         try {  
  33.             md = MessageDigest.getInstance("SHA-1");  
  34.             // 将三个参数字符串拼接成一个字符串进行 shal 加密  
  35.             byte[] digest = md.digest(content.toString().getBytes());  
  36.             tmpStr = byteToStr(digest);  
  37.         } catch (NoSuchAlgorithmException e) {  
  38.             // TODO Auto-generated catch block  
  39.             e.printStackTrace();  
  40.         }  
  41.         content = null;  
  42.         // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信  
  43.         return tmpStr != null ? tmpStr.equals(signature.toUpperCase()): false;  
  44.     }  
  45.       
  46.     /** 
  47.      * 将字节数组转换为十六进制字符串 
  48.      * @param digest 
  49.      * @return 
  50.      */  
  51.     private static String byteToStr(byte[] digest) {  
  52.         // TODO Auto-generated method stub  
  53.         String strDigest = "";  
  54.         for(int i = 0; i < digest.length; i++){  
  55.             strDigest += byteToHexStr(digest[i]);  
  56.         }  
  57.         return strDigest;  
  58.     }  
  59.       
  60.     /** 
  61.      * 将字节转换为十六进制字符串 
  62.      * @param b 
  63.      * @return 
  64.      */  
  65.     private static String byteToHexStr(byte b) {  
  66.         // TODO Auto-generated method stub  
  67.         char[] Digit = {'0''1''2''3''4''5''6''7''8''9''A''B''C''D''E''F'};  
  68.         char[] tempArr = new char[2];  
  69.         tempArr[0] = Digit[(b >>> 4) & 0X0F];  
  70.         tempArr[1] = Digit[b & 0X0F];  
  71.           
  72.         String s = new String(tempArr);  
  73.         return s;  
  74.     }  
  75. }  

   最后,看看代码,代码应该不会出错的了,但是,在类名 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 中有这么一句代码:

[java]  view plain copy
  1. private static String token = "weixinface";  

   代码中的 token 的值我们可以随意写,但是,这里是什么值,在微信平台上就要填写对应的内容,所有,在 Token 那里填上 weixinface,点击“提交”,如果代码没有问题,瞬间你就可以看到“你已成为开发者” 的提示,如图 :



    到此,所有的工作都已经完成,你可以不断丰富你的代码,实现不同的功能。你也可以在自己的微信中关注自己的订阅号,只需扫描公众平台的二维码就行了。     


欢迎关注我的订阅号:天龙智能
二维码:


郑重声明
    本博客的代码是来自柳老师的 博客 (  http://blog.csdn.net/column/details/wechatmp.html   )我只是作为一种补充,我希望以此方式来表达我对柳老师的感谢之情,完全没有盗版之意,如有侵犯,请联系我,谢谢
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值