你的位置:首页 > Java教程

[Java教程]Java与微信不得不说的故事——实现微信公众平台与sae服务器的对接


  又颓废了些日子,说好认真来半年的,那就接着来啊,公司的easyUI平台慢慢开始明白了,可是最近bug太多了,只能找时间在研究了,平时无聊看见了了java微信平台开发,感觉有点意思呀,自己也来试试,不过又得求教博客园里面的大神们了,现在开始研究。

  一开始无聊的时候,自己在新浪云服务器注册了一个账号,可以建立一些应用在上面,微信平台也是可以的。于是自己照着微信官方的例子,建立了微信公众平台与新浪云服务器的接口,成功了。不过官方是用PHP语言写的(也许PHP是世界上最好的语言)。可是作为一个Javaer,当然要学会怎么写Java了。先贴把这个例子贴一下吧。

  

<?php/** * wechat php test *///define your tokendefine("TOKEN", "haojiahongxihuanliyuan");$wechatObj = new wechatCallbackapiTest();$wechatObj->valid();class wechatCallbackapiTest{  public function valid()  {    $echoStr = $_GET["echostr"];    //valid signature , option    if($this->checkSignature()){      echo $echoStr;      exit;     }  }  public function responseMsg()  {    //get post data, May be due to the different environments    $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];     //extract post data    if (!empty($postStr)){        /* lib*/        libtrue);         $postObj = simple($postStr, 'Simple LIB$fromUsername = $postObj->FromUserName;        $toUsername = $postObj->ToUserName;        $keyword = trim($postObj->Content);        $time = time();        $textTpl = "<";               if(!empty( $keyword ))        {           $msgType = "text";          $contentStr = "Welcome to wechat world!";          $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);          echo $resultStr;        }else{          echo "Input something...";        }    }else {      echo "";      exit;    }  }      private function checkSignature()  {    // you must define TOKEN by yourself    if (!defined("TOKEN")) {      throw new Exception('TOKEN is not defined!');    }        $signature = $_GET["signature"];    $timestamp = $_GET["timestamp"];    $nonce = $_GET["nonce"];            $token = TOKEN;    $tmpArr = array($token, $timestamp, $nonce);    // use SORT_STRING rule    sort($tmpArr, SORT_STRING);    $tmpStr = implode( $tmpArr );    $tmpStr = sha1( $tmpStr );        if( $tmpStr == $signature ){      return true;    }else{      return false;    }  }}?>

  这个是官方提过的接口程序。

  下面开始研究Java接口程序。

  当用户通过微信客服端发送消息到微信服务后,微信服务器会将此消息转发给我们的公网服务器,也就是上面所说sae新浪云服务器。具体的业务逻辑就在sae上完成,处理完后再将结果发回微信服务器,微信服务器再发给用户。

  让两个完全不沾边的服务器(微信服务器和sae)对接是有风险,因此必须有验证机制的存在。具体的验证过程是

代码如下:

微信公众平台去请求sae中的coreServlet。

package org.liufeng.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;import org.liufeng.course.service.CoreService;import org.liufeng.course.util.SignUtil;/** * 请求处理的核心类 * * @author liufeng * @date 2013-09-29 */public class CoreServlet extends HttpServlet {  private static final long serialVersionUID = 4440739483644821986L;  /**   * 请求校验(确认请求来自微信服务器)   */  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    // 微信加密签名    String signature = request.getParameter("signature");    // 时间戳    String timestamp = request.getParameter("timestamp");    // 随机数    String nonce = request.getParameter("nonce");    // 随机字符串    String echostr = request.getParameter("echostr");    PrintWriter out = response.getWriter();    // 请求校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败    if (SignUtil.checkSignature(signature, timestamp, nonce)) {      out.print(echostr);    }    out.close();    out = null;  }  /**   * 处理微信服务器发来的消息   */  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    // 将请求、响应的编码均设置为UTF-8(防止中文乱码)    request.setCharacterEncoding("UTF-8");    response.setCharacterEncoding("UTF-8");    // 调用核心业务类接收消息、处理消息    String resp CoreService.processRequest(request);    // 响应消息    PrintWriter out = response.getWriter();    out.print(resp

消息处理类:

package org.liufeng.course.util;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Arrays;/** * 请求校验工具类 * * @author liufeng * @date 2013-09-01 */public class SignUtil {  // 与开发模式接口配置信息中的Token保持一致  private static String token = "weixinCourse";  /**   * 校验签名   *   * @param signature 微信加密签名   * @param timestamp 时间戳   * @param nonce 随机数   * @return   */  public static boolean checkSignature(String signature, String timestamp, String nonce) {    // 对token、timestamp和nonce按字典排序    String[] paramArr = new String[] { token, timestamp, nonce };    Arrays.sort(paramArr);    // 将排序后的结果拼接成一个字符串    String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);    String ciphertext = null;    try {      MessageDigest md = MessageDigest.getInstance("SHA-1");      // 对接后的字符串进行sha1加密      byte[] digest = md.digest(content.toString().getBytes());      ciphertext = byteToStr(digest);    } catch (NoSuchAlgorithmException e) {      e.printStackTrace();    }        // 将sha1加密后的字符串与signature进行对比    return ciphertext != null ? ciphertext.equals(signature.toUpperCase()) : false;  }  /**   * 将字节数组转换为十六进制字符串   *   * @param byteArray   * @return   */  private static String byteToStr(byte[] byteArray) {    String strDigest = "";    for (int i = 0; i < byteArray.length; i++) {      strDigest += byteToHexStr(byteArray[i]);    }    return strDigest;  }  /**   * 将字节转换为十六进制字符串   *   * @param mByte   * @return   */  private static String byteToHexStr(byte mByte) {    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[(mByte >>> 4) & 0X0F];    tempArr[1] = Digit[mByte & 0X0F];    String s = new String(tempArr);    return s;  }}

web.

<??><web-app version="2.5" ="http://java.sun.com/  ="http://www.w3.org/2001/  xsi:schemaLocation="http://java.sun.com/>  <servlet>    <servlet-name>coreServlet</servlet-name>    <servlet-class>      org.liufeng.course.servlet.CoreServlet    </servlet-class>  </servlet>  <!-- /coreServlet用于指定该Servlet的访问路径 -->  <servlet-mapping>    <servlet-name>coreServlet</servlet-name>    <url-pattern>/coreServlet</url-pattern>  </servlet-mapping>  <welcome-file-list>    <welcome-file>index.jsp</welcome-file>  </welcome-file-list></web-app>

微信公众平台的配置截图:

微信平台提示接入成功。