From 6fb5228c49607ece809d6aedf119825ab82c4a3c Mon Sep 17 00:00:00 2001 From: TangCheng <tangchengmail@163.com> Date: 星期三, 05 三月 2025 20:07:28 +0800 Subject: [PATCH] 完善代码 --- JAVA/SMTAIServer/src/main/java/com/smtaiserver/smtaiserver/control/SMTAIWeixinControl.java | 416 ++++++++++++++++++++++++++++++++++++----------------------- 1 files changed, 254 insertions(+), 162 deletions(-) diff --git a/JAVA/SMTAIServer/src/main/java/com/smtaiserver/smtaiserver/control/SMTAIWeixinControl.java b/JAVA/SMTAIServer/src/main/java/com/smtaiserver/smtaiserver/control/SMTAIWeixinControl.java index 2a84b06..14a49e5 100644 --- a/JAVA/SMTAIServer/src/main/java/com/smtaiserver/smtaiserver/control/SMTAIWeixinControl.java +++ b/JAVA/SMTAIServer/src/main/java/com/smtaiserver/smtaiserver/control/SMTAIWeixinControl.java @@ -1,200 +1,284 @@ package com.smtaiserver.smtaiserver.control; +import cn.hutool.http.HttpUtil; import com.smtaiserver.smtaiserver.core.SMTAIServerApp; -import com.smtaiserver.smtaiserver.vo.MediaVo; -import com.smtaiserver.smtaiserver.vo.WechatMessageVO; +import com.smtaiserver.smtaiserver.core.SMTAIServerRequest; +import com.smtaiserver.smtaiserver.database.SMTDatabase; +import com.smtaiserver.smtaiserver.database.SMTDatabase.DBRecords; +import com.smtaiserver.smtaiserver.javaai.ast.ASTDBMap; +import com.smtaiserver.smtaiserver.javaai.llm.core.SMTLLMConnect; import com.smtservlet.core.SMTRequest; +import com.smtservlet.util.Json; +import com.smtservlet.util.SMTJsonWriter; +import com.smtservlet.util.SMTStatic; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; -import org.springframework.boot.configurationprocessor.json.JSONException; import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.web.servlet.ModelAndView; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; import java.io.IOException; import java.io.OutputStream; -import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; import static java.util.Arrays.sort; public class SMTAIWeixinControl { + private static final String FROM_USER_NAME = "FromUserName"; private static final String TO_USER_NAME = "ToUserName"; private static final String CONTENT = "Content"; - private final String accessToken = - "89_pBAY9bgHt-7gBy2N8k_s31PMV3KFY1xgy_yCLw8eMHLqpugmHv2RXUgwf-2HC6bq5XPzVloiZp4ccnHDUfumjEOGxeFwFqIp8-gLU3OrPneiKgkv4l0mxd_orTAHNPgAJANTV"; - private static Logger _logger = LogManager.getLogger(SMTAIServerControl.class); + private Object _lockToken = new Object(); + private String _tokenValue = null; + private long _tokenTicket = 0; + /** 寰俊楠岃瘉 */ - public ModelAndView weChatNotify(SMTRequest tranReq) throws Exception { + public ModelAndView weChatNotify(SMTAIServerRequest tranReq) throws Exception { String method = tranReq.getRequest().getMethod(); if (method.equals("GET")) return getModelAndView(tranReq); return reply(tranReq); } /** 琚姩鍥炲 */ - private ModelAndView reply(SMTRequest tranReq) throws Exception { + private ModelAndView reply(SMTAIServerRequest tranReq) throws Exception { HttpServletRequest request = tranReq.getRequest(); Map<String, String> requestMap = getWechatReqMap(request); if (requestMap.isEmpty()) { return null; } - + // wechatMessage.setFromUserName(requestMap.get(TO_USER_NAME)); + // wechatMessage.setToUserName(requestMap.get(FROM_USER_NAME)); + // wechatMessage.setCreateTime(System.currentTimeMillis() / 1000); + String xmltemp = + "<xml>\n" + + " <ToUserName><![CDATA[{{{toUser}}}]]></ToUserName>\n" + + " <FromUserName><![CDATA[{{{fromUser}}}]]></FromUserName>\n" + + " <CreateTime>{{{CreateTime}}}</CreateTime>\n" + + " <MsgType><![CDATA[text]]></MsgType>\n" + + " <Content><![CDATA[鎴戞鍦ㄦ�濊�冨摝~璇风◢绛夆�︹�]></Content>\n" + + "</xml>"; + long l = System.currentTimeMillis() / 1000; + String createTimeStr = String.valueOf(l); // 灏� long 杞崲涓� String + // 鏇挎崲鍗犱綅绗� + String result = + xmltemp + .replace("{{{toUser}}}", requestMap.get(FROM_USER_NAME)) + .replace("{{{fromUser}}}", requestMap.get(TO_USER_NAME)) + .replace("{{{CreateTime}}}", createTimeStr); String reqContent = requestMap.get(CONTENT); - WechatMessageVO wechatMessage = new WechatMessageVO(); - wechatMessage.setFromUserName(requestMap.get(TO_USER_NAME)); - wechatMessage.setToUserName(requestMap.get(FROM_USER_NAME)); // 璁剧疆娑堟伅绫诲瀷 - switch (reqContent) { - case "鏂囧瓧": - wechatMessage.setMsgType("text"); - break; - case "鍥剧墖": - wechatMessage.setMsgType("image"); - break; - case "璇煶": - wechatMessage.setMsgType("voice"); - break; - case "瑙嗛": - wechatMessage.setMsgType("video"); - break; - case "闊充箰": - wechatMessage.setMsgType("music"); - break; - case "鍥炬枃": - wechatMessage.setMsgType("news"); - break; - default: - wechatMessage.setMsgType("text"); - break; - } + // switch (reqContent) { + // case "鏂囧瓧": + // wechatMessage.setMsgType("text"); + // break; + // case "鍥剧墖": + // wechatMessage.setMsgType("image"); + // break; + // case "璇煶": + // wechatMessage.setMsgType("voice"); + // break; + // case "瑙嗛": + // wechatMessage.setMsgType("video"); + // break; + // case "闊充箰": + // wechatMessage.setMsgType("music"); + // break; + // case "鍥炬枃": + // wechatMessage.setMsgType("news"); + // break; + // default: + // wechatMessage.setMsgType("text"); + // break; + // } - wechatMessage.setCreateTime(System.currentTimeMillis() / 1000); - MediaVo media = new MediaVo(); - - wechatMessage.setContent("鎴戞鍦ㄦ�濊�冨摝~璇风◢绛夆�︹��"); - // 寮傛璋冪敤 aiReplyToTheUserASecondTime - CompletableFuture.runAsync( - () -> { - try { - //aiReplyToTheUserASecondTime(tranReq, requestMap.get(FROM_USER_NAME)); - String answer = callAIForAnswerQuestion(reqContent); - - } catch (Exception e) { - e.printStackTrace(); - } - }); - - + // MediaVo media = new MediaVo(); + // wechatMessage.setContent("鎴戞鍦ㄦ�濊�冨摝~璇风◢绛夆�︹��"); + // 寮傛璋冪敤 aiReplyToTheUserASecondTime + CompletableFuture.runAsync( + () -> { + try { + String answer = callAIForAnswerQuestion(reqContent, tranReq); // Ai璋冪敤 杩斿洖缁撴灉 + aiReplyToTheUserASecondTime(answer, requestMap.get(FROM_USER_NAME)); + } catch (Exception e) { + _logger.error("aiReplyToTheUserASecondTime error", e); + } + }); + // 璁剧疆娑堟伅鍐呭 -// switch (reqContent) { -// case "鏂囧瓧": -// wechatMessage.setContent("鎴戞鍦ㄦ�濊�冨摝~璇风◢绛夆�︹��"); -// // 寮傛璋冪敤 aiReplyToTheUserASecondTime -// CompletableFuture.runAsync( -// () -> { -// try { -// aiReplyToTheUserASecondTime(tranReq, requestMap.get(FROM_USER_NAME)); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// }); -// break; -// case "鍥剧墖": -// media.setMediaId("SI7HPwMI5PL1QV_I9M5AFw6K-1ZVMyTGE0-a5jQM4czTmffKTQpHa6zlYDmvIAPX"); -// wechatMessage.setImage(media); -// break; -// case "璇煶": -// media.setMediaId("c6hRH_X2HGwrOa1MiTQAcg35D7M42Xa4VMhyzSFMk8MA0pWFhly19W4K3W5NaH4b"); -// wechatMessage.setVoice(media); -// break; -// case "瑙嗛": -// media.setMediaId("c6hRH_X2HGwrOa1MiTQAcmo7zQjGAIV7uSP1U1S-tsnR0VJXUS0y10Z5FkaueU5Y"); -// media.setTitle("浣犲ソ"); -// media.setDescription("浣犲ソ鍟�"); -// wechatMessage.setVideo(media); -// break; -// case "闊充箰": -// System.out.println("杩涘叆闊充箰鍒嗘敮"); -// break; -// case "鍥炬枃": -// System.out.println("杩涘叆鍥炬枃鍒嗘敮"); -// break; -// default: -// System.out.println("杩涘叆榛樿鍒嗘敮"); -// wechatMessage.setContent("鎴戜笉澶璇嗕綘鐨勮緭鍏ュ摝"); -// break; -// } + // switch (reqContent) { + // case "鏂囧瓧": + // wechatMessage.setContent("鎴戞鍦ㄦ�濊�冨摝~璇风◢绛夆�︹��"); + // // 寮傛璋冪敤 aiReplyToTheUserASecondTime + // CompletableFuture.runAsync( + // () -> { + // try { + // aiReplyToTheUserASecondTime(tranReq, requestMap.get(FROM_USER_NAME)); + // } catch (Exception e) { + // e.printStackTrace(); + // } + // }); + // break; + // case "鍥剧墖": + // media.setMediaId("SI7HPwMI5PL1QV_I9M5AFw6K-1ZVMyTGE0-a5jQM4czTmffKTQpHa6zlYDmvIAPX"); + // wechatMessage.setImage(media); + // break; + // case "璇煶": + // media.setMediaId("c6hRH_X2HGwrOa1MiTQAcg35D7M42Xa4VMhyzSFMk8MA0pWFhly19W4K3W5NaH4b"); + // wechatMessage.setVoice(media); + // break; + // case "瑙嗛": + // media.setMediaId("c6hRH_X2HGwrOa1MiTQAcmo7zQjGAIV7uSP1U1S-tsnR0VJXUS0y10Z5FkaueU5Y"); + // media.setTitle("浣犲ソ"); + // media.setDescription("浣犲ソ鍟�"); + // wechatMessage.setVideo(media); + // break; + // case "闊充箰": + // System.out.println("杩涘叆闊充箰鍒嗘敮"); + // break; + // case "鍥炬枃": + // System.out.println("杩涘叆鍥炬枃鍒嗘敮"); + // break; + // default: + // System.out.println("杩涘叆榛樿鍒嗘敮"); + // wechatMessage.setContent("鎴戜笉澶璇嗕綘鐨勮緭鍏ュ摝"); + // break; + // } try { // 灏� WechatMessageVO 瀵硅薄杞崲涓� XML - JAXBContext jaxbContext = JAXBContext.newInstance(WechatMessageVO.class); - Marshaller marshaller = jaxbContext.createMarshaller(); - marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); - StringWriter sw = new StringWriter(); - marshaller.marshal(wechatMessage, sw); - _logger.info("寰俊娑堟伅杩斿弬锛�" + sw); + // JAXBContext jaxbContext = JAXBContext.newInstance(WechatMessageVO.class); + // Marshaller marshaller = jaxbContext.createMarshaller(); + // marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + // StringWriter sw = new StringWriter(); + // marshaller.marshal(wechatMessage, sw); + _logger.info("寰俊娑堟伅杩斿弬锛�" + result); // 杩斿洖 XML 瀛楃涓� - return tranReq.returnText(sw.toString()); - } catch (JAXBException e) { + return tranReq.returnText(result); + } catch (Exception e) { throw new RuntimeException(e); } } - - private String callAIForAnswerQuestion(String question) - { - return "ssss"; - } /** - * 浜屾鍥炲 + * ai鍥炲 * - * @param tranReq - * @return * @throws Exception */ - public ModelAndView aiReplyToTheUserASecondTime(SMTRequest tranReq, String fromUserName) + private String callAIForAnswerQuestion(String question, SMTAIServerRequest tranReq) throws Exception { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("touser", "oKAHz7LQhyL2IkcMpl8B7K4OotQk"); - jsonObject.put("msgtype", "text"); - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.put("content", "浣犲ソ鍟�"); - jsonObject.put("text", jsonObject1); - _logger.info("jsonObject: {}", jsonObject); - // 鏋勫缓涓婁紶 URL + String callFunc = + "query_water_fee:\n" + + " 鍔熻兘锛歕n" + + " 鏌ヨ鐢ㄦ埛鐢ㄦ按閲忓拰姘磋垂淇℃伅\n" + + " 鍙傛暟:\n" + + " question:鐢ㄦ埛闂\n" + + " user_name:鐢ㄦ埛鍚峔n" + + " value_title:'鐢ㄦ按閲�'鎴�'姘磋垂'\n" + + " value_name:鐢ㄦ按閲忥細volume, 姘磋垂:amount\n" + + " start_time:鏌ヨ璧峰鏃ユ湡锛屾牸寮忥細骞�-鏈�-鏃n" + + " end_time:鏌ヨ缁撴潫鏃堕棿锛屾牸寮忥細骞�-鏈�-鏃n"; + + String prompt = + ((String) SMTAIServerApp.getApp().getGlobalConfig("prompt.agent_tools")) + .replace("{{{AGENT_TOOL_DEFINE_LIST}}}", callFunc); + + SMTLLMConnect llm = SMTAIServerApp.getApp().allocLLMConnect(null); + String answer = llm.callWithMessage(new String[] {prompt}, question, tranReq); + tranReq.traceLLMDebug(answer); + Json ojsonASTList = SMTStatic.convLLMAnswerToJson(answer, true); + if(ojsonASTList != null && ojsonASTList.isArray()) + { + List<Json> jsonASTList = ojsonASTList.asJsonList(); + if (jsonASTList.size() > 0) + { + Json jsonAST = jsonASTList.get(0); + if ("query_water_fee".equals(jsonAST.safeGetStr("call", null))) { + jsonAST = jsonAST.getJson("args"); + try (ASTDBMap dbMap = new ASTDBMap()) { + SMTDatabase db = dbMap.getDatabase("DS_74_CHENGTOU"); + DBRecords recs = + db.querySQL( + " SELECT ROUND(SUM(" + + jsonAST.getJson("value_name").asString() + + ")::NUMERIC(10, 2), 2) AS TOTAL" + + " FROM chengtou_data.bill_data WHERE billing_date BETWEEN ? AND ?", + new Object[] { + SMTStatic.toDate(jsonAST.getJson("start_time").asString()), + SMTStatic.toDate(jsonAST.getJson("end_time").asString()) + }); + + if (recs.getRecord(0).getString(0) == null) + return "浠�" + + jsonAST.getJson("start_time").asString() + + "鍒�" + + jsonAST.getJson("end_time").asString() + + "鐨�" + + jsonAST.getJson("value_title").asString() + + "鏈煡鍒颁换浣曟暟鎹�"; + + return "浠�" + + jsonAST.getJson("start_time").asString() + + "鍒�" + + jsonAST.getJson("end_time").asString() + + "鐨�" + + jsonAST.getJson("value_title").asString() + + "鎬昏" + + recs.getRecord(0).getString(0) + + ("volume".equals(jsonAST.getJson("value_name").asString()) ? "鍚�" : "鍏�") + ; + } + } + } + } + answer = llm.callWithMessage(null, question, tranReq); + + return answer; + } + + /** 浜屾鍥炲 */ + public ModelAndView aiReplyToTheUserASecondTime(String answer, String fromUserName) + throws Exception { + String accessToken = getAccessToken(); + + SMTJsonWriter jsonWr = new SMTJsonWriter(false); + jsonWr.addKeyValue("touser", fromUserName); + jsonWr.addKeyValue("msgtype", "text"); + jsonWr.beginMap("text"); + { + jsonWr.addKeyValue("content", answer); + } + jsonWr.endMap(); + // JSONObject jsonObject = new JSONObject(); + // jsonObject.put("touser", fromUserName); + // jsonObject.put("msgtype", "text"); + // JSONObject jsonObject1 = new JSONObject(); + // jsonObject1.put("content", answer); + // jsonObject.put("text", jsonObject1); + // _logger.info("jsonObject: {}", jsonObject); String url = String.format( "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s", accessToken); - // String body = HttpRequest.post(url).form(String.valueOf(jsonObject)).timeout(20000)//瓒呮椂锛屾绉� - // .execute().body(); - Map<String, Object> stringObjectMap = jsonObjectToMap(jsonObject); - String s = sendPost(url, stringObjectMap); + // Map<String, Object> stringObjectMap = jsonObjectToMap(jsonWr.getRootJson()); + String s = sendPost(url, jsonWr.getRootJson()); _logger.info("涓婁紶缁撴灉: {}", s); return null; } - - + /** 寰俊楠岃瘉 */ private static ModelAndView getModelAndView(SMTRequest tranReq) throws Exception { String signature = tranReq.convParamToString("signature", true); String timestamp = tranReq.convParamToString("timestamp", true); @@ -214,43 +298,35 @@ return tranReq.returnText(""); } - public static Map<String, Object> jsonObjectToMap(JSONObject jsonObject) throws JSONException { - Map<String, Object> map = new HashMap<>(); - Iterator<String> keys = jsonObject.keys(); + public String getAccessToken() throws Exception { + synchronized (this._lockToken) { + if (_tokenValue == null || (System.currentTimeMillis() - _tokenTicket) > 3600 * 1000) { + HashMap<String, String> weixinParam = getWeixinParam(); + String url = + "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + + weixinParam.get("appId") + + "&secret=" + + weixinParam.get("secret"); + String response = HttpUtil.get(url); + JSONObject jsonObject = new JSONObject(response); + if (jsonObject.has("access_token")) { + String accessToken = jsonObject.getString("access_token"); - while (keys.hasNext()) { - String key = keys.next(); - Object value = jsonObject.get(key); - - // 濡傛灉鍊兼槸 JSONObject锛岄�掑綊杞崲涓� Map - if (value instanceof JSONObject) { - value = jsonObjectToMap((JSONObject) value); + _tokenValue = accessToken; + } else { + throw new Exception("can't get weixin token : " + jsonObject.toString()); + } + _tokenTicket = System.currentTimeMillis(); } - - map.put(key, value); + return _tokenValue; } - - return map; } - /** - * 楠岃瘉绛惧悕 - * - * @param signature - * @param timestamp - * @param nonce - * @return - */ + /** 楠岃瘉绛惧悕util */ public static boolean checkSignature(String signature, String timestamp, String nonce) throws Exception { - Object weixinParam = SMTAIServerApp.getApp().getGlobalConfig("weixin_core_param", "false"); - _logger.info("寰俊鍙傛暟锛歿}", weixinParam); - JSONObject weixinJson = new JSONObject(weixinParam.toString()); - Object appId = weixinJson.get("appId"); - Object secret = weixinJson.get("secret"); - String token = (String) weixinJson.get("token"); - - String[] arr = new String[] {token, timestamp, nonce}; + HashMap<String, String> weixinParam = getWeixinParam(); + String[] arr = new String[] {weixinParam.get("token"), timestamp, nonce}; // 灏唗oken銆乼imestamp銆乶once涓変釜鍙傛暟杩涜瀛楀吀搴忔帓搴� // Arrays.sort(arr); sort(arr); @@ -274,6 +350,21 @@ return tmpStr != null && tmpStr.equals(signature.toUpperCase()); } + + private static HashMap<String, String> getWeixinParam() throws Exception { + Object weixinParam = SMTAIServerApp.getApp().getGlobalConfig("weixin_core_param", "false"); + _logger.info("寰俊鍙傛暟锛歿}", weixinParam); + JSONObject weixinJson = new JSONObject(weixinParam.toString()); + String appId = (String) weixinJson.get("appId"); + String secret = (String) weixinJson.get("secret"); + String token = (String) weixinJson.get("token"); + HashMap<String, String> paramMap = new HashMap<>(); + paramMap.put("appId", appId); + paramMap.put("secret", secret); + paramMap.put("token", token); + return paramMap; + } + public static Map<String, String> getWechatReqMap(HttpServletRequest request) { Map<String, String> requestMap = new HashMap<>(); SAXReader reader = new SAXReader(); @@ -289,6 +380,7 @@ } return requestMap; } + /** * 灏嗗瓧鑺傛暟缁勮浆鎹负鍗佸叚杩涘埗瀛楃涓� * @@ -318,10 +410,10 @@ return s; } - public static String sendPost(String urlString, Map<String, Object> params) throws Exception { + public static String sendPost(String urlString, Json jsonParam) throws Exception { // 灏嗗弬鏁拌浆鎹负 JSON 鏍煎紡瀛楃涓� - JSONObject jsonParams = new JSONObject(params); - String payload = jsonParams.toString(); + // JSONObject jsonParams = new JSONObject(params); + String payload = jsonParam.toString(); // 鍒涘缓杩炴帴 URL url = new URL(urlString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); -- Gitblit v1.9.3