框架是groovy的框架grails ,但还是用java写的,有些地方跟java还是稍微有一丢丢不一样的,不过不碍事的
class AutoReplyController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
//输入自己的公众号token
private static final TOKEN = "YOUR TOKEN";
//图灵机器人开发key
private static final APIKEY = "YOUR APIKEY";
/**
* 微信后台主入口,所有的通过微信后台服务器转接到系统的方法全部由此入口登录
* @author slash
* @since 2015年6月4日17:38:34
* @return
*/
def mainPort(){
String methods = request.getMethod();
HashMap<String, String> data = new HashMap<String, String>();
boolean listFlag = false;
boolean urlFlag = false;
boolean trainFlag = false;
boolean planeFlag = false;
boolean newsFlag = false;
boolean eatFlag = false;
StringBuffer replyString = new StringBuffer("<xml>\n");
//验证服务器地址有效性
if(request.getMethod().equals("GET")||request.getMethod().equals("get")){
boolean result = checkSignature(params.signature, params.timestamp, params.nonce, TOKEN);
if(result)
render params.echostr;
}
//具体业务主入口
else {
try {
InputStream inputStream = request.getInputStream();
// 创建saxReader对象
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
Element element = document.getRootElement();
List<Element> list = element.elements();
Map<String, Object> map = new HashMap<String, Object>();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
if (map.get("MsgType") != null && map.get("MsgType").equals("text")) {
//打通图灵机器人
String massageInfo = URLEncoder.encode(map.get("Content"), "utf-8");
String getURL = "http://www.tuling123.com/openapi/api?key=" + APIKEY + "&info=" + massageInfo;
URL getUrl = new URL(getURL);
HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
connection.connect();
// 取得输入流,并使用Reader读取
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( connection.getInputStream(), "utf-8"));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
//第一层JSON解析对象
JSONObject dataJson = new JSONObject(sb.toString());
//第二层JSON解析对象
JSONObject listJson
Iterator it = dataJson.keys();
//遍历最外层JSON
while (it.hasNext()){
String key = String.valueOf(it.next());
String value = (String) dataJson.get(key);
//当获取到的key是list,即返回结果为新闻,列车,航班,菜谱
if(key.equals("list")){
listFlag = true;
String a = value.substring(1,value.length()-1);
listJson = new JSONObject(value.substring(1,value.length()-1));
Iterator listIt = listJson.keys();
//遍历list中的JSON
while (it.hasNext()){
String listKey = String.valueOf(listIt.next());
//当获取的list中的key是trainnum时,即返回结果为列车
if(listKey.equals("trainnum")){
trainFlag = true;
break;
}
if(listKey.equals("flight")){
planeFlag = true;
break;
}
if(listKey.equals("article")){
newsFlag = true;
break;
}
if(listKey.equals("name")){
eatFlag = true;
break;
}
}
}
//当获取到的key是url,即返回结果为链接时
if(key.equals("url")){
urlFlag = true;
}
}
ReplyForImageAndText replyForImageAndText = new ReplyForImageAndText();
replyForImageAndText.toUserName = map.get("FromUserName");
replyForImageAndText.fromUserName = map.get("ToUserName");
replyForImageAndText.msgType = map.get("MsgType");
replyForImageAndText.articleCount = 1;
//如果返回结果为列车
if(listFlag && trainFlag){
ImageAndTextDetail imageAndTextDetail = new ImageAndTextDetail();
imageAndTextDetail.description = "车次:"+listJson.get("trainnum")+"; 起始站:"+
listJson.get("start")+"; 终点站:"+listJson.get("terminal")+"; 开车时间:"+
listJson.get("starttime")+"; 到达时间:"+listJson.get("endtime");
imageAndTextDetail.picUrl = listJson.get("icon").toString();
imageAndTextDetail.url = listJson.get("detailurl").toString();
replyString.append("<ToUserName><![CDATA[" + replyForImageAndText.toUserName + "]]></ToUserName>\n");
replyString.append("<FromUserName><![CDATA[" + replyForImageAndText.fromUserName + "]]></FromUserName>\n");
replyString.append("<CreateTime>" + replyForImageAndText.createTime + "</CreateTime>\n");
replyString.append("<MsgType><![CDATA[news]]></MsgType>\n");
replyString.append("<ArticleCount>" + replyForImageAndText.articleCount + "</ArticleCount>\n");
replyString.append("<Articles>\n");
replyString.append("<item>\n");
replyString.append("<Title><![CDATA[" + dataJson.get("text") + "]]></Title>\n");
replyString.append("<Description><![CDATA[" + imageAndTextDetail.description + "]]></Description>\n");
replyString.append("<PicUrl><![CDATA[" + imageAndTextDetail.picUrl + "]]></PicUrl>\n");
replyString.append("<Url><![CDATA[" + imageAndTextDetail.url + "]]></Url>\n");
replyString.append("</item>\n");
replyString.append("</Articles>\n");
replyString.append("</xml>");
}
//如果返回结果为航班
else if(listFlag && planeFlag){
ImageAndTextDetail imageAndTextDetail = new ImageAndTextDetail();
imageAndTextDetail.description = "航班次:"+listJson.get("flight")+"; 航班路线:"+
listJson.get("route")+"; 起飞时间:"+
listJson.get("starttime")+"; 到达时间:"+listJson.get("endtime")+"; 航班状态:"+
listJson.get("state");
imageAndTextDetail.picUrl = listJson.get("icon").toString();
imageAndTextDetail.url = listJson.get("detailurl").toString();
replyString.append("<ToUserName><![CDATA[" + replyForImageAndText.toUserName + "]]></ToUserName>\n");
replyString.append("<FromUserName><![CDATA[" + replyForImageAndText.fromUserName + "]]></FromUserName>\n");
replyString.append("<CreateTime>" + replyForImageAndText.createTime + "</CreateTime>\n");
replyString.append("<MsgType><![CDATA[news]]></MsgType>\n");
replyString.append("<ArticleCount>" + replyForImageAndText.articleCount + "</ArticleCount>\n");
replyString.append("<Articles>\n");
replyString.append("<item>\n");
replyString.append("<Title><![CDATA[" + dataJson.get("text") + "]]></Title>\n");
replyString.append("<Description><![CDATA[" + imageAndTextDetail.description + "]]></Description>\n");
replyString.append("<PicUrl><![CDATA[" + imageAndTextDetail.picUrl + "]]></PicUrl>\n");
replyString.append("<Url><![CDATA[" + imageAndTextDetail.url + "]]></Url>\n");
replyString.append("</item>\n");
replyString.append("</Articles>\n");
replyString.append("</xml>");
}
//如果返回结果为新闻
else if(listFlag && newsFlag){
ImageAndTextDetail imageAndTextDetail = new ImageAndTextDetail();
imageAndTextDetail.description = "标题:"+listJson.get("article")+"; 来源:"+
listJson.get("source");
imageAndTextDetail.picUrl = listJson.get("icon").toString();
imageAndTextDetail.url = listJson.get("detailurl").toString();
replyString.append("<ToUserName><![CDATA[" + replyForImageAndText.toUserName + "]]></ToUserName>\n");
replyString.append("<FromUserName><![CDATA[" + replyForImageAndText.fromUserName + "]]></FromUserName>\n");
replyString.append("<CreateTime>" + replyForImageAndText.createTime + "</CreateTime>\n");
replyString.append("<MsgType><![CDATA[news]]></MsgType>\n");
replyString.append("<ArticleCount>" + replyForImageAndText.articleCount + "</ArticleCount>\n");
replyString.append("<Articles>\n");
replyString.append("<item>\n");
replyString.append("<Title><![CDATA[" + dataJson.get("text") + "]]></Title>\n");
replyString.append("<Description><![CDATA[" + imageAndTextDetail.description + "]]></Description>\n");
replyString.append("<PicUrl><![CDATA[" + imageAndTextDetail.picUrl + "]]></PicUrl>\n");
replyString.append("<Url><![CDATA[" + imageAndTextDetail.url + "]]></Url>\n");
replyString.append("</item>\n");
replyString.append("</Articles>\n");
replyString.append("</xml>");
}
//如果返回结果为菜谱
else if(listFlag && eatFlag){
ImageAndTextDetail imageAndTextDetail = new ImageAndTextDetail();
imageAndTextDetail.description = "菜名:"+listJson.get("name")+"; 详情:"+
listJson.get("info");
imageAndTextDetail.picUrl = listJson.get("icon").toString();
imageAndTextDetail.url = listJson.get("detailurl").toString();
replyString.append("<ToUserName><![CDATA[" + replyForImageAndText.toUserName + "]]></ToUserName>\n");
replyString.append("<FromUserName><![CDATA[" + replyForImageAndText.fromUserName + "]]></FromUserName>\n");
replyString.append("<CreateTime>" + replyForImageAndText.createTime + "</CreateTime>\n");
replyString.append("<MsgType><![CDATA[news]]></MsgType>\n");
replyString.append("<ArticleCount>" + replyForImageAndText.articleCount + "</ArticleCount>\n");
replyString.append("<Articles>\n");
replyString.append("<item>\n");
replyString.append("<Title><![CDATA[" + dataJson.get("text") + "]]></Title>\n");
replyString.append("<Description><![CDATA[" + imageAndTextDetail.description + "]]></Description>\n");
replyString.append("<PicUrl><![CDATA[" + imageAndTextDetail.picUrl + "]]></PicUrl>\n");
replyString.append("<Url><![CDATA[" + imageAndTextDetail.url + "]]></Url>\n");
replyString.append("</item>\n");
replyString.append("</Articles>\n");
replyString.append("</xml>");
}
//如果返回结果为链接
else if(urlFlag){
ReplyForUrl replyForUrl = new ReplyForUrl();
replyForUrl.toUserName = map.get("FromUserName");
replyForUrl.fromUserName = map.get("ToUserName");
replyForUrl.msgType = map.get("MsgType");
replyForUrl.msgId = BigInteger.valueOf(Long.valueOf(map.get("MsgId")));
replyForUrl.contentUrl = dataJson.get("text")+",点击查询";
replyString.append("<ToUserName><![CDATA[" + replyForUrl.toUserName + "]]></ToUserName>\n");
replyString.append("<FromUserName><![CDATA[" + replyForUrl.fromUserName + "]]></FromUserName>\n");
replyString.append("<CreateTime>" + replyForUrl.createTime + "</CreateTime>\n");
replyString.append("<MsgType><![CDATA[" + replyForUrl.msgType + "]]></MsgType>\n");
replyString.append("<Content><![CDATA[<a href = '" + dataJson.get("url")+ "'>"+replyForUrl.contentUrl+"</a>]]></Content>\n");
replyString.append("</xml>");
}
else {
ReplyForText replyForText = new ReplyForText();
replyForText.toUserName = map.get("FromUserName");
replyForText.fromUserName = map.get("ToUserName");
replyForText.msgType = map.get("MsgType");
replyForText.msgId = BigInteger.valueOf(Long.valueOf(map.get("MsgId")));
replyForText.createTime = 15529131405;
replyForText.content = dataJson.get("text");
replyString.append("<ToUserName><![CDATA[" + replyForText.toUserName + "]]></ToUserName>\n");
replyString.append("<FromUserName><![CDATA[" + replyForText.fromUserName + "]]></FromUserName>\n");
replyString.append("<CreateTime>" + replyForText.createTime + "</CreateTime>\n");
replyString.append("<MsgType><![CDATA[" + replyForText.msgType + "]]></MsgType>\n");
replyString.append("<Content><![CDATA[" + replyForText.content + "]]></Content>\n");
replyString.append("</xml>");
}
}
render replyString.toString();
} catch (Exception e) {
e.printStackTrace();
}
}
}
<pre name="code" class="java"> /**
* 检查请求是否合法
* @param signature
* @param timestamp
* @param nonce
* @param token
* @return
* @throws Exception
*/
private boolean checkSignature(String signature, String timestamp, String nonce, String token) throws Exception{
String[] tmpArr = new String[3];
tmpArr[0] = token;
tmpArr[1] = timestamp;
tmpArr[2] = nonce;
Arrays.sort(tmpArr);//对字符串数组 排序
String tmpStr = getArrayStr(tmpArr);
String sha1 = makeSHA1(tmpStr);
if(signature.equals(sha1))
return true;
return false;
}
/**
* 获得字符串数组的字符串形式
* @param array
* @return
*/
private String getArrayStr(String[] array){
StringBuffer sb = new StringBuffer();
for(int i = 0; i < array.length; i++){
sb.append(array[i]);
}
return sb.toString();
}
/**
* 对字符串进行SHA1加密
* @param tmpStr
* @return
* @throws Exception
*/
private String makeSHA1(String tmpStr) throws Exception{
MessageDigest md = MessageDigest.getInstance("SHA-1");//获取MessageDigest实例
md.update(tmpStr.getBytes());
byte[] tmpArr = md.digest();
return byteToHex(tmpArr);
}
/**
* 将二进制数据转化为十六进制数据串
* @param arr
* @return
*/
private String byteToHex(byte[] arr){
String hs = "";
String tmp = "";
for(int i = 0; i < arr.length; i++){
tmp = Integer.toHexString(arr[i] & 0xFF);
if(tmp.length() < 2){
tmp = "0" + tmp;
}
hs = hs + tmp;
}
return hs;
}
下面是各个对象类
class ReplyForText {
static constraints = {
}
//发送至 的微信号
String toUserName;
//来自于 的微信号
String fromUserName;
//回复 创建时间
BigInteger createTime;
//消息类别:文字,图文,视频,音频,地理位置
String msgType;
//内容
String content;
//消息Id
BigInteger msgId;
}
class ReplyForUrl {
static constraints = {
}
//发送至 的微信号
String toUserName;
//来自于 的微信号
String fromUserName;
//回复 创建时间
BigInteger createTime;
//消息类别:文字,图文,视频,音频,地理位置
String msgType;
//内容
String contentUrl;
//消息Id
BigInteger msgId;
}
class ReplyForImageAndText {
static constraints = {
}
//发送至 的微信号
String toUserName;
//来自于 的微信号
String fromUserName;
//回复 创建时间
BigInteger createTime;
//消息类别:文字,图文,视频,音频,地理位置
String msgType;
//图文消息个数,限制为10条以内
Integer articleCount;
}
class ImageAndTextDetail {
static constraints = {
}
//图文消息标题
String title;
//图文消息描述
String description;
//图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
String picUrl;
//点击图文消息跳转链接
String url;
}