لقد كنت مشغولاً بالوقت الأمامي لفترة من الوقت. لقد قرأت المستندات من نقطة الصفر واتخذت على العديد من المزالق. لقد مررت به مؤخرًا. لقد فكرت في إجراء بعض الملخصات حتى أتمكن من مراجعته في المستقبل عندما أقوم بتطويره. سأشير أيضًا إلى الطلاب الذين يعملون في المشاريع ذات الصلة.
في الواقع ، بعد القيام بذلك مرة واحدة ، ستجد أنه ليس من الصعب. الفكرة العامة هي: رسائل المستخدم ودفع الأحداث المطلوبة من قبل المطورين ستبدأ طلبًا من خلال خادم WeChat وإعادة توجيهه إلى عنوان عنوان URL الخادم الذي قمت بتكوينه على النظام الأساسي العام. سيحضر خادم WeChat أربعة معلمات: التوقيع ، الطابع الزمني ، nonce ، و echosttr. سيقوم خادمنا بتوصيل الرمز المميز الذي تم تكوينه بواسطة النظام الأساسي العام وحمّل الطابع الزمني. سيتم تشفير nonce في SHA1 وتطابق التوقيع. أعد ture للإشارة إلى أن الوصول ناجح.
1. تكوين النظام الأساسي العام
2.controller
@controller@requestmapping ("/wechat") publicclass wechatcontroller {value ("$ {dnbx_token}") private string dnbx_token ؛ private static final logger = loggerfactory.getlogger (wechatcontroller.class) ؛ @return * throws ioException */ @requestmapping (value = "/connect" ، method = {requestMethod.get ، requestmethod.post}) @responsepublidpublicvoid connectweixin (httpservledquest request ، ustrening ust-response) response) request.setcharacterencoding ("UTF-8") ؛ // يستخدم خادم WeChat ترميز UTF-8 عند نشر الرسائل ، ويجب استخدام نفس الترميز عند الاستلام ، وإلا فإن التعليمات البرمجية المشوهة الصينية ستكون رمز مشجعة ؛ استجابة. setcharacterencoding ("UTF-8") ؛ // عند الرد على الرسائل (الرد على المستخدم) ، يتم أيضًا تعيين طريقة الترميز على UTF-8 ، والمبدأ هو نفسه كما هو مذكور أعلاه ؛ منطقية isget = request.getMethod (). printWriter Out = response.getWriter () ؛ حاول {if (isGet) {string signature = request.getParameter ("signature") ؛ // wechat encryption signature string timestamp = request.getParameter ("timestamp") ؛ // timestamp string nonce = request.getParameter ("nonce") ؛ سلسلة // تحقق من الطلب عن طريق التحقق من التوقيع. إذا كان التحقق ناجحًا ، فاحصل على Echosttr كما هو ، مما يشير إلى أن الوصول ناجح. خلاف ذلك ، يفشل الوصول إذا (signutil.checksignature (dnbx_token ، التوقيع ، الطابع الزمني ، nonce)) {logger.info ("توصيل خادم Weixin ناجح.") ؛ استجابة. } آخر {logger.error ("فشل في التحقق من التوقيع!") ؛ }} else {string represmessage = "استثناء رسالة!" ؛ جرب {respmessage = weChatservice.weixinpost (request) ؛ out.write (respmessage) ؛ logger.info ("requist exclude bantaived") Weixin! ") ؛ }}} catch (استثناء e) {logger.error (3. التحقق من التحقق من التوقيع
من وحدة التحكم أعلاه ، يمكننا أن نرى أنني أغلف علامة فئة الأدوات ، تسمى checksiscishature ، وتم تمريرها في أربع قيم ، DNBX_TOKEN ، التوقيع ، الطابع الزمني ، nonce. هذه العملية مهمة جدا. في الواقع ، يمكننا أن نفهمها على أنها عملية تشفير وفك تشفير القيمة التي يتم نقلها بواسطة WeChat. من أجل ضمان الأمن ، سيكون لجميع الواجهات في العديد من المشاريع الكبيرة عملية التحقق هذه. dnbx_token قمنا بتكوين سلسلة رمزية على منصة WeChat العامة ، حافظ على سرية الفكرة! الثلاثة الأخرى هي المعلمات التي يتم إرسالها بواسطة خادم WeChat لإرسال طلب الحصول على. نؤدي طبقة من تشفير SHA1:
الفئة العامة signutil { / *** توقيع التحقق* param token wechat server token ، يجب أن يكون تكوينه في ملف env.properties وتكوينه في مركز المطورين ثابتًا* signature server wechat يرسل رقم sha1 string string string (string tokenature* string timestamp* timestamp timestamp* publaram boolen to string to string tok. التوقيع ، سلسلة الطابع الزمني ، سلسلة nonce) {string [] arr = new string [] {token ، timestamp ، nonce} ؛ // فرز ترتيب القاموس من الرمز المميز ، الطابع الزمني ، و nonce ؛ // لصق سلاسل المعلمة الثلاثة في سلسلة لسلسلة تشفير SHA1 TMPSTR = sha1.encode (arr [0] + arr [1] + arr [2]) ؛ // يمكن مقارنة السلسلة المشفرة SHA1 بالتوقيع ، مع تحديد أن الطلب يأتي من WeChat Return TMPSTR! = NULL؟ TMPSTR.Equals (Signature.ToupperCase ()): خطأ ؛ }}SHA1:
/** * منصة WeChat العامة (Java) SDK * * SHA1 خوارزمية * Author Helijun 2016/06/15 19: 49 */Public Final Class Sha1 {Private Static Final Char [] "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، "،" ، 'b' ، 'c' ، 'd' ، 'e' ، 'f'} ؛ /*** يأخذ البايتات الخام من Digest وتنسيقها بشكل صحيح. * * param بايت بايت الخام من الهضم. * @العودة البايتات المنسقة. */ 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 () ؛ } تشفير السلسلة الثابتة العامة (String str) {if (str == null) {return null ؛ } جرب {messagedigest messagedigest = messagedigest.getInstance ("sha1") ؛ messagedigest.update (str.getBytes ()) ؛ return getFormattedText (messagedigest.digest ()) ؛ } catch (استثناء e) {رمي new runTimeException (e) ؛ }}} عند إرسالها وحفظها على المنصة العامة ورؤية المطالبة الخضراء "نجاح الوصول" ، تهانينا على إكمال وصول WeChat. تتطلب هذه العملية المزيد من العناية والانتباه إلى الحالة في خوارزمية التشفير. إذا لم يكن الوصول ناجحًا ، فإن معظم الحالات هي مشاكل في خوارزمية التشفير ، تحقق من ذلك أكثر.
4. تنفيذ خدمة رد الرسائل التلقائية
/*** طلبات العملية من WeChat** param request* @return*/public string weixinpost (طلب httpservletrequest) {string respmessage = null ؛ try {// xml request map <string ، string> requestMap = messageutitil.xmltomap (request) ؛ requestmap.get ("fromuserName") ؛ // سلسلة الحساب العامة touserName = requestMap.get ("touserName") ؛ // نوع الرسالة سلسلة msgtype = requestMap.get ("msgtype") ؛ "، msgtype هو:" + msgtype) ؛ // رسالة نصية if (msgtype.equals (messageutil.req_message_type_text)) {// يتم تنفيذ المنطق المقابل وفقًا للكلمات الرئيسية. لا يوجد سوى واحد لا يمكنك تخيله. لا يوجد شيء لا يمكنك فعله إذا (content.equals ("xxx")) {} // الرد التلقائي textMessage = new textMessage () ؛ text.setContent ("النص" + محتوى) "") ؛ text.setmsgtype (msgtype) ؛ respmessage = messageUtil.textMessageToxMl (text) ؛}/*else if (msgtype.equals (messageutil.req_message_type_event)) (eventType.equals (messageutil.event_type_subscribe)) {// الاشتراك في respcontent = "مرحبًا بمتابعة الحساب الرسمي xxx! eventKey = requestMap.get ("EventKey") ؛ // قيمة مفتاح الحدث ، المقابلة لقيمة المفتاح المحددة عند إنشاء logger.info المخصصة ("EventKey is:" +eventKey) ؛ return xxx ؛ requestMap.get ("التعرف") ؛ // respcontent = "استلام نتيجة تحليل الكلام:"+recvmessage ؛ if (recvmessage! = null) {respcontent = tulingapiprocess.getTulingResult (recvmessage) ؛} else {respcontent = "ما قلته غامض للغاية ، هل يمكنك قول ذلك مرة أخرى؟ } // وظيفة التصوير الفوتوغرافي إذا كان (msgtype.equals ("pic_sysphoto")) {} آخر {return messageresponse.getTextMessage (fromusername ، touserName ، "return leght") ؛ }*// event push else else if (msgtype.equals (messageutil.req_message_type_event)) {string eventtype = requestMap.get ("event") اتبع ، xxx ") ؛ text.settouserName (fromuserName) ؛ text.setFromuserName (touserName) ؛ text.setCreateTime (تاريخ جديد (). getTime () +" ") إلغاء الاشتراك ، لا يمكن للمستخدم استلام الرسالة التي يتم إرسالها بواسطة الحساب الرسمي ، لذلك ليست هناك حاجة للرد على رسالة أخرى إذا (EventType.equals (messageutil.event_type_unsubscribe)) {// unsbexke} قيمة مفتاح الحدث ، المقابلة لقيمة المفتاح المحددة عند إنشاء القائمة المخصصة if (eventKey.equals ("customer_telephone")) {textMessage text = new textMessage () ؛ text.setContent ("0755-86671980") DATE ().تم نشر الرمز على النحو الوارد أعلاه. معظمهم لديهم تعليقات. إذا قرأت الدلالات الأساسية مرة واحدة ، فلن تحتاج إلى شرحها.
فكرة موجزة: عندما يرسل المستخدم رسالة إلى الحساب الرسمي ، سيطلب خادم WeChat رسالة المستخدم من خلال المنشور إلى الواجهة المقابلة للخادم الذي قمنا بتكوينه بتنسيق XML. ما يتعين علينا القيام به هو إجراء المعالجة المنطقية المقابلة بناءً على نوع الرسالة ، وما إلى ذلك ، وإرجاع نتيجة الإرجاع النهائية إلى خادم WeChat من خلال تنسيق XML ، ثم نقله إلى المستخدم.
هناك مكان واحد يحتاج إلى عناية خاصة:
إن اسم FromuserName و tousername الأحمر هو عكس ذلك تمامًا ، وهو أيضًا أحد المزالق. أتذكر أنني قمت بتعديله لفترة طويلة ، لكنها لم تكن مشكلة ، لكنها لم تكن تعمل. أخيرًا ، تلقيت الرسالة بعد تغيير هذين! في الواقع ، من الصحيح التفكير في الأمر. عندما تعود إلى خادم WeChat ، سيتغير دورك ، وبالتالي فإن المرسل والمستقبل هو بالتأكيد عكس ذلك.
5.Messageutil
فئة عامة messageutil {/ *** نوع الرسالة الإرجاع: Text*/ public static Final String Resp_Message_Type_text = "text" ؛ / *** نوع الرسالة الإرجاع: Music*/ public Static Final String resp_message_type_music = "music" ؛ / *** نوع الرسالة الإرجاع: نص الرسوم*/ السلسلة النهائية الثابتة العامة resp_message_type_news = "الأخبار" ؛ / *** نوع رسالة الطلب: Text*/ Public Static Final String req_message_type_text = "text" ؛ / *** نوع الرسالة نوع الرسالة: الصورة*/ السلسلة النهائية الثابتة العامة req_message_type_image = "Image" ؛ / *** نوع الطلب نوع الرسالة: الرابط*/ السلسلة النهائية الثابتة العامة req_message_type_link = "link" ؛ / *** نوع رسالة الطلب: الموقع الجغرافي*/ السلسلة النهائية الثابتة العامة req_message_type_location = "الموقع" ؛ / *** نوع رسالة الطلب: الصوت*/ السلسلة النهائية الثابتة العامة req_message_type_voice = "Voice" ؛ / ** * نوع رسالة الطلب: Push */ public Static Final String req_message_type_event = "event" ؛ / ** * نوع الحدث: اشتراك (اشترك) */ static Static Final String event_type_subscribe = "اشتراك" ؛ / ** * نوع الحدث: إلغاء الاشتراك (إلغاء الاشتراك) */ السلسلة النهائية الثابتة العامة event_type_unsubscribe = "unbscribe" ؛ / ** * نوع الحدث: انقر فوق (قائمة مخصصة انقر فوق الحدث) */ السلسلة النهائية الثابتة العامة event_type_click = "انقر فوق" ؛ }هنا ، من أجل جعل البرنامج قابلية للقراءة وقابلية التوسع أفضل ، قمت بإجراء بعض التغليف ، وحددت العديد من الثوابت ، وتغليف بعض المعلمات التي تم تمريرها من WeChat إلى كائنات Java Bean الثابتة. الرمز الأساسي كما هو مذكور أعلاه. ركز على التحويل بين XML والخريطة
في الواقع ، تعزى هذه المشكلة إلى WeChat باستخدام اتصال XML ، وعادة ما نستخدم JSON ، لذلك قد نشعر بعدم الارتياح قليلاً في فترة زمنية قصيرة.
1. حزمة جرة
<!-parse xml-> <redency> <roupid> dom4j </rougiD> <artifactId> dom4j </stifactid> <الإصدار> 1.6.1 </version> </dependency> <redency> <roucid> com.theaughworks.xstream </roughid>
2.xml على كائن جمع الخريطة
/. = null ؛ حاول {ins = request.getInputStream () ؛} catch (ioException e1) {e1.printstacktrace () ؛} docum doc = null ؛ try {doc = reader.read (ins) ؛ element root = doc.getRootelement () ؛ list <element> list = elem. E.GetText ()) ؛} خريطة الإرجاع ؛} 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 () ؛ما سبق هو مقدمة المحرر إلى Java لتنفيذ SPRINGMVC WeChat Access وتنفيذ وظيفة الرد التلقائي البسيط. آمل أن يكون ذلك مفيدًا للجميع. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر على الجميع في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!