Некоторое время назад я был занят. Я начал разрабатывать официальную учетную запись WeChat и читать документы с нуля. Я наступил на множество ловушек. Я прошел через это. Недавно я подумал о том, чтобы сделать некоторое резюме, чтобы я мог просмотреть его, когда я разрабатываю его в будущем. Я также дам ссылку на студентов, которые работают над соответствующими проектами.
1. Идеи
WeChat Access: Сообщения пользователя и нажилки событий, требуемые разработчиками, инициируют запрос через сервер WeChat и пересылают адрес URL -адреса сервера, который вы настроили на общедоступной платформе. Сервер WeChat принесет четыре параметра подписи, TimeStamp, Nonce и EchoStr. Наш собственный сервер разбивает токен, настроенный на общедоступной платформе, а также загруженная метка времени, а Nonce зашифруется в SHA1 и соответствует подписи. Верните туру, чтобы указать, что доступ успешен.
Ответ сообщения: Когда пользователь отправляет сообщение в официальную учетную запись, сервер WeChat запросит пользовательское сообщение на соответствующий интерфейс сервера, который мы настроили в формате XML через сообщение. Что мы должны сделать, так это выполнить соответствующую логическую обработку на основе типа сообщения и т. Д., И вернуть окончательный результат возврата на сервер WeChat через формат XML, и сторона WeChat передаст его пользователю.
1. Общедоступная конфигурация платформы
2. Контроллер
@Controller @requestMapping ("/weChat") publicClass weChatController {@Value ("$ {dnbx_token}") частная строка dnbx_token; Private Static Final Logger logger = loggerFactory.getLogger (weChatController.class); @Resource wechatservice wechatservice; /** * WeChat access* @param wc * @return * @throws IOException */ @RequestMapping(value="/connect",method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody publicvoid connectWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException{ // Set the encoding of the request and response для UTF-8 (предотвратить просьбу китайского). // Сервер WeChat использует кодирование UTF-8 при сообщении почты, и при получении необходимо использовать то же кодирование, в противном случае китайская искажающая response.setcharacterencoding ("UTF-8"); // При ответе на сообщения (отвечая на пользователя) метод кодирования также установлен на UTF-8, принцип такой же, как и выше; boolean isget = request.getMethod (). tolowercase (). equals ("get"); Printwriter Out = response.getWriter (); try {if (isget) {string signature = request.getParameter ("signature"); // weChat шифровать подпись строки строки timeStamp = request.getParameter ("timestamp"); // timestamp String nonce = request.getParameter ("nonce"); // random string echoStr = request.getParameter ("echeStr"); подпись. Если проверка успешна, верните EchoStr, как есть, указывая на то, что доступ успешен. В противном случае, доступ не работает, если (signutil.checksignature (dnbx_token, signature, timestamp, nonce)) {logger.info («Подключение сервера Weixin успешно.»); response.getWriter (). написать (echoStr); } else {logger.error ("Не удалось проверить подпись!"); }} else {string respmessage = "Сообщение об исключении!"; try {respmessage = wechatservice.weixinpost (запрос); out.write (respmessage); Logger.info («Запрос завершен успешно»); Logger.info ("to weixin server"+respmessage); } catch (Exception e) {logger.error ("Не удалось преобразовать сообщение из Weixin!"); }}} catch (Exception e) {logger.error ("Подключить сервер weixin is error."); } наконец {out.close (); }}}3. Проверка подписи.
Из контроллера выше мы видим, что я инкапсуляю сигнал класса инструментов, называемый контрольной сигнализацией и прошел в четыре значения, DNBX_TOKEN, Signature, TimeStamp, Nonce. Этот процесс очень важен. На самом деле, мы можем понять это как процесс шифрования и дешифрования значения, передаваемого WeChat. Чтобы обеспечить безопасность, все интерфейсы во многих крупных проектах будут иметь такой процесс проверки. DNBX_TOKEN Мы настроили токеновую строку на общедоступной платформе WeChat, сохраняйте идею конфиденциальной! Остальные три - это параметры, отправленные сервером WeChat для отправки запроса GET. Мы выполняем слой шифрования SHA1:
открытый класс Signutil { / *** Подписание проверки* @param token token weChat token Server, настроенный в файле env.properties и настроенный в центре разработчиков должен быть согласованной* @param signature. Сервер WeChat отправляет SHA1 Scrypted Sertiactiate* @param timestamp Timestam подпись, строка временной метки, строка nonce) {string [] arr = new String [] {token, timestamp, nonce}; // Сортировка словаря порядок токена, временной метки и нонсе; // сплачивать три строки параметров в строку для строки шифрования SHA1 TMPSTR = SHA1.ENCODE (ARR [0] + ARR [1] + ARR [2]); // Строка зашифрованного SHA1 можно сравнить с подписью, определяя, что запрос поступает от weChat return tmpstr! = NULL? tmpstr.equals (signature.touppercase ()): false; }} SHA1:
/** * WeChat Public Platform (Java) SDK * * Sha1 Algorithm * @author helijun 2016/06/15 19:49 */public final Class sha1 {private static final char [] hex_digits = {'0', '1', '2', ',' 4 ', 5', '6', '7', ',', ',', ',', ',', ',', ',', '7 'B', 'c', 'd', 'e', 'f'}; /*** берет сырые байты из дайки и форматирует их правильно. * * @param байт необработанных байтов из дайджеста. * @return Отформатированные байты. */ private static String getFormattedText (byte [] bytes) {int len = bytes.length; StringBuilder buf = new StringBuilder (Len * 2); // преобразовать шифровый текст в шестнадцатеричную строковую форму для (int j = 0; j <len; j ++) {buf.append (hex_digits [(bytes [j] >> 4) & 0x0f]); buf.append (hex_digits [bytes [j] & 0x0f]); } return buf.toString (); } public Static String Encode (String Str) {if (str == null) {return null; } try {MessageDigest messageDigest = messagedigest.getInstance ("sha1"); MessageDigest.Update (str.getBytes ()); return getFormattedText (messagegest.digest ()); } catch (Exception e) {бросить новое runtimeexception (e); }}}Когда вы отправляете и сохраняете его на общедоступной платформе и видите зеленую подсказку «успех доступа», поздравляю с завершением доступа WeChat. Этот процесс требует немного большей осторожности и обратите внимание на случай в алгоритме шифрования. Если доступ не является успешным, большинство случаев являются проблемами с алгоритмом шифрования, проверьте его больше.
4. Реализация службы автоматического ответа сообщения
/ ** * Запросы на процесс от WeChat * * @param запрос * @return */ public String weixinpost (httpservletrequest) {string respmessage = null; try {// xml -запрос карты анализа <string, string> requestmap = messageutil.xmltomap (request); // учетная запись отправителя (open_id) string fromusername = requestmap.get ("fromusername"); // Строка публичной учетной записи tousername = requestmap.get ("tousername"); // тип сообщения string msgtype = requestmap.get ("msgtype"); // Содержимое содержимого сообщества содержимое = requestMap.get ("content"); Logger.info ("fromUserName IS:" + fromUsername + ", tousername IS:" + tousername + ", msgtype is:" + msgtype); // Текстовое сообщение if (msgtype.equals (messageUtil.req_message_type_text)) {// здесь вы выполняете соответствующую логику в соответствии с ключевыми словами, есть только одна, о которой вы не можете придумать, и нет такой вещи, как вы не можете сделать, если (content.equals ("xx")) {} // automatic out -reply textmess extexcess = equals ("xx")) {} // automatic outemessage =); Text.SetContent («Текст - + контент); Text.SetTouserName (FromUsername); text.setfromusername (tousername); Text.SetCreatetime (new Date (). getTime () + ""); text.setmsgtype (msgtype); respmessage = messageutil.textmessageToxml (текст); } /*else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {// Event push String eventType = requestMap.get("Event");// Event type if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {// Subscribe to respContent = "Welcome to follow the xxx official account! "; return messageresponse.gettextmessage (от ususername, tousername, respcontent); } else if (eventtype.equals (messageUtil.event_type_click)) {// пользовательское меню Нажмите String String eventKey = requestMap.get ("evenceKey"); // Значение ключа события, соответствующее значению ключа, указанного при создании пользовательского меню logger.info ("Event Event:" +EventKey); вернуть XXX; }} // Включите тест на распознавание звука WeChat 2015-3-30 else if (msgtype.equals ("vicoor")) {string recvmessage = requestmap.get ("распознавание"); // respcontent = "Полученный результат анализа речи:"+recvmessage; if (recvmessage! = null) {respcontent = tulingApipRocess.getTulingResult (recvMessage); } else {respcontent = "То, что вы сказали, слишком расплывчато, вы можете сказать это снова?"; } return messageresponse.getTextMessage (fromUsername, tousername, respcontent); } // Функция фотографии else if (msgtype.equals ("pic_sysphoto")) {} else {return messageresponse.getTextMessage (fromUsername, tousername, "return to pelly"); }*/ // event push else if (msgtype.equals (messageUtil.req_message_type_event)) {string eventtype = requestmap.get ("event"); // event // подписаться if (eventtype.equals (messagetil.event_type_subcribe)) {textmess = nehtemess =; text.setContent ("Добро пожаловать, xxx"); Text.SetTouserName (FromUsername); text.setfromusername (tousername); Text.SetCreatetime (new Date (). getTime () + ""); text.setmsgtype (messageutil.resp_message_type_text); respmessage = messageutil.textmessageToxml (текст); } // todo После отмены подписки пользователь не может получить сообщение, отправленное официальной учетной записью, поэтому не нужно отвечать на сообщение Else if (EventType.equals (messageUtil.event_type_unsubscribe)) {// unsubscribe} // custom menu click evence) eventype.equals.equals. requestMap.get ("eventKey"); // Значение ключа события соответствует значению ключа, указанному при создании пользовательского меню if (evenceKey.equals ("customer_telephone")) {textmessage text = new TextMessage (); Text.SetContent ("0755-86671980"); Text.SetTouserName (FromUsername); text.setfromusername (tousername); Text.SetCreatetime (new Date (). getTime () + ""); text.setmsgtype (messageutil.resp_message_type_text); respmessage = messageutil.textmessageToxml (текст); }}}} catch (Exception e) {logger.error ("error ...")} return respmessage; }Код опубликован, как указано выше. У большинства из них есть комментарии. Если вы читаете основную семантику один раз, вам не нужно их объяснять.
Есть одно место, которое требует особого внимания:
Красный цвет от имени и tousername - именно противоположность, что также является одной из ловушек. Я помню, что я долгое время отрегулировал его, но это не было проблемой, но это не работало. Наконец, я получил сообщение после изменения этих двух! На самом деле, правильно думать об этом. Когда вы вернетесь на сервер WeChat, ваша роль изменится, поэтому отправитель и приемник определенно противоположны.
5.messageutil
Открытый класс MessageUtil { / *** Возвращение сообщения типа: текст* / public Static String String resp_message_type_text = "text"; / *** Возвращение сообщения типа: музыка*/ public Static Final String resp_message_type_music = "music"; / *** Возвращение сообщения: графический текст*/ public static final String resp_message_type_news = "News"; / *** Тип сообщения запроса: текст*/ public static final String req_message_type_text = "text"; / *** Тип сообщения запроса: Image*/ public Static Final String req_message_type_image = "Image"; / *** Тип сообщения запроса: ссылка*/ public static final String req_message_type_link = "link"; / *** Тип сообщения запроса: географическое местоположение*/ public static final String req_message_type_location = "location"; / *** Тип сообщения запроса: Audio*/ public static final String req_message_type_voice = "ocole"; / ** * Тип сообщения запроса: push */ public static final String req_message_type_event = "event"; / ** * Тип события: подписка (подписаться) */ public static final String event_type_subscribe = "Подписаться"; / ** * Тип события: UNSOUBSCRIBE (USOUBSCRIBE) */ Public Static Final String Event_type_unsubscribe = "UnsubScribe"; / ** * Тип события: нажмите (Custom Menu Click Event) */ public Static Final String Event_type_click = "click"; }Здесь, чтобы улучшить читаемость и масштабируемость программы, я сделал некоторую инкапсуляцию, определил несколько констант и инкапсулировал некоторые параметры, передаваемые из WeChat в постоянные объекты Java. Основной код, как и выше. Сосредоточьтесь на преобразовании между XML и MAP
На самом деле, эта проблема связана с WeChat с использованием связи XML, и мы обычно используем JSON, поэтому мы можем чувствовать себя немного неудобно за короткий период времени.
1. Пакет банки
<!-Parse XML-> <Dependency> <groupId> dom4j </GroupId> <artifactid> dom4j </artifactid> <sersive> 1.6.1 </version> </depertive> <dehydency> <groupid> com.thoughtworks.xstream </Ground> <strifactid> xstream </artifactid> <serse> 1.4.9 </.9.9 </.4.9 </.4.9 </.9.9 </.4.9 </.4.9 </.4.9 </.1.9 </Ground> <//ArtifactId> </.4.9 </Ground> <//ArtifactId> <//4.
2.xml для карты объекта сбора
/ ** * xml для карты * @param запрос * @return * @throws ioexception */ @suppresswarnings ("unchecked") public static map <string, string> xmltomap (httpservletrequest) прописывает ioexception {map <string> map = new hashmap <string, string> (); SaxReader Reader = new SaxReader (); InputStream ins = null; try {ins = request.getInputStream (); } catch (ioException e1) {e1.printstacktrace (); } Документ doc = null; try {doc = reader.read (ins); Элемент root = doc.getRootelement (); List <element> list = root.elements (); for (element e: list) {map.put (e.getName (), e.getText ()); } return Map; } catch (documentException e1) {e1.printstacktrace (); } наконец {ins.close (); } return null; } 3. Преобразование объекта текстового сообщения в XML
/ ** * Конвертировать объект текстового сообщения в xml * * @param textmessage объект текстового сообщения * @return xml */ public Static String TextMessageToxml (TextMessage TextMessage) {xStream XStream = new XStream (); xstream.alias ("xml", textmessage.getClass ()); вернуть xstream.toxml (textmessage); } До сих пор работа была завершена. В настоящее время вы можете попытаться отправить «тест» в официальной учетной записи. Вы получите ответ «Текст текст». Это также процесс ответа, сделанный в приведенном выше коде. Конечно, вы также можете использовать свое воображение, чтобы сделать все, что вы хотите сделать, например, ответить на 1, чтобы проверить погоду, 2 проверить нарушения и т. Д. ....
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.