ฉันยุ่งไปสักพักแล้ว ฉันเริ่มพัฒนาบัญชีอย่างเป็นทางการของ WeChat และอ่านเอกสารตั้งแต่เริ่มต้น ฉันก้าวไปสู่ข้อผิดพลาดมากมาย ฉันผ่านมันไปแล้ว ฉันเพิ่งพิจารณาสรุปบางอย่างเพื่อให้ฉันสามารถตรวจสอบได้เมื่อฉันพัฒนามันในอนาคต ฉันจะให้การอ้างอิงถึงนักเรียนที่ทำงานในโครงการที่เกี่ยวข้อง
1. ไอเดีย
WeChat Access: ข้อความผู้ใช้และเหตุการณ์ที่ผู้พัฒนาต้องการจะเริ่มต้นการร้องขอผ่าน WeChat Server และส่งต่อไปยังที่อยู่ URL ของเซิร์ฟเวอร์ที่คุณกำหนดค่าบนแพลตฟอร์มสาธารณะ เซิร์ฟเวอร์ WeChat จะนำพารามิเตอร์ทั้งสี่ของลายเซ็นการประทับเวลา nonce และ echostr เซิร์ฟเวอร์ของเราประกบโทเค็นที่กำหนดค่าโดยแพลตฟอร์มสาธารณะรวมถึงการอัปโหลดเวลาที่อัปโหลดและ Nonce ถูกเข้ารหัสใน SHA1 และจับคู่ลายเซ็น ส่งคืน ture เพื่อระบุว่าการเข้าถึงสำเร็จ
การตอบกลับข้อความ: เมื่อผู้ใช้ส่งข้อความไปยังบัญชีอย่างเป็นทางการเซิร์ฟเวอร์ WeChat จะขอข้อความผู้ใช้ไปยังอินเทอร์เฟซที่เกี่ยวข้องของเซิร์ฟเวอร์ที่เรากำหนดค่าในรูปแบบ XML ผ่านโพสต์ สิ่งที่เราต้องทำคือการประมวลผลเชิงตรรกะที่สอดคล้องกันตามประเภทข้อความ ฯลฯ และส่งคืนผลลัพธ์การส่งคืนสุดท้ายไปยังเซิร์ฟเวอร์ WeChat ผ่านรูปแบบ XML และ WeChat Party จะส่งไปยังผู้ใช้
1. การกำหนดค่าแพลตฟอร์มสาธารณะ
2. เครื่องควบคุม
@controller @requestmapping ("/weChat") publicclass weChatController {@Value ("$ {dnbx_token}") สตริงส่วนตัว dnbx_token; Logger Logger สุดท้ายคงที่ = loggerFactory.getLogger (weChatController.class); @Resource wechatservice wechatservice; /** * การเข้าถึง weChat * @param wc * @return * @throws ioexception */@requestmapping (value = "/เชื่อมต่อ", method = {requestMethod.get, requestMethod.post}) @ResponseBody PublicVoid CONNECTWEIXIN การตอบสนองต่อ UTF-8 (ป้องกันไม่ให้ภาษาจีนอ่านไม่ออก) การร้องขอ Setcharacterencoding ("UTF-8"); // เซิร์ฟเวอร์ WeChat ใช้การเข้ารหัส UTF-8 เมื่อข้อความโพสต์และการเข้ารหัสเดียวกันจะต้องใช้เมื่อได้รับมิฉะนั้นภาษาจีนที่อ่านไม่ออกจะเป็น; Response.Setcharacterencoding ("UTF-8"); // เมื่อตอบกลับข้อความ (ตอบกลับผู้ใช้) วิธีการเข้ารหัสจะถูกตั้งค่าเป็น UTF-8 หลักการเหมือนกับข้างต้น บูลีน isget = request.getMethod (). toLowerCase (). เท่ากับ ("รับ"); PrintWriter out = response.getWriter (); ลอง {ถ้า (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, ลายเซ็น, timestamp, nonce)) {logger.info ("เชื่อมต่อเซิร์ฟเวอร์ Weixin สำเร็จ"); Response.getWriter (). เขียน (echostr); } else {logger.error ("ไม่สามารถตรวจสอบลายเซ็น!"); }} else {string respmessage = "ข้อความยกเว้น!"; ลอง {respmessage = wechatservice.weixinpost (คำขอ); out.write (respmessage); logger.info ("คำขอเสร็จสมบูรณ์"); logger.info ("ไปยัง Weixin Server"+respmessage); } catch (exception e) {logger.error ("ไม่สามารถแปลงข้อความจาก Weixin!"); }}} catch (exception e) {logger.error ("เชื่อมต่อเซิร์ฟเวอร์ Weixin เป็นข้อผิดพลาด"); } ในที่สุด {out.close (); -3. การตรวจสอบการตรวจสอบลายเซ็น
จากคอนโทรลเลอร์ด้านบนเราจะเห็นว่าฉันห่อหุ้มตัวบ่งชี้คลาสเครื่องมือที่เรียกว่าการตรวจสอบและส่งผ่านในสี่ค่า DNBX_Token, ลายเซ็น, การประทับเวลา, nonce กระบวนการนี้สำคัญมาก ในความเป็นจริงเราสามารถเข้าใจได้ว่าเป็นกระบวนการเข้ารหัสและถอดรหัสของค่าที่ส่งโดย WeChat เพื่อให้มั่นใจว่าการรักษาความปลอดภัยอินเทอร์เฟซทั้งหมดในโครงการขนาดใหญ่จำนวนมากจะมีกระบวนการตรวจสอบดังกล่าว dnbx_token เราได้กำหนดค่าสตริงโทเค็นบนแพลตฟอร์มสาธารณะ WeChat ทำให้ความคิดเป็นความลับ! อีกสามตัวคือพารามิเตอร์ที่ส่งโดย WeChat Server เพื่อส่งคำขอ GET เราทำการเข้ารหัส SHA1:
Signutil คลาสสาธารณะ { / *** ลายเซ็นการตรวจสอบ* @param โทเค็นโทเค็นเซิร์ฟเวอร์ Wechat เซิร์ฟเวอร์ที่กำหนดค่าในไฟล์ env.properties และกำหนดค่าในศูนย์นักพัฒนาซอฟต์แวร์จะต้องสอดคล้อง* @param ลายเซ็นเซิร์ฟเวอร์ weChat ส่ง sha1 @sha1 โทเค็น, ลายเซ็นสตริง, สตริง timestamp, สตริง nonce) {string [] arr = สตริงใหม่ [] {โทเค็น, timestamp, nonce}; // เรียงลำดับพจนานุกรมของโทเค็น, การประทับเวลาและ nonce; // splice สตริงพารามิเตอร์สามตัวลงในสตริงสำหรับ SHA1 การเข้ารหัสสตริง tmpstr = sha1.encode (arr [0] + arr [1] + arr [2]); // สตริงที่เข้ารหัส sha1 สามารถเปรียบเทียบกับลายเซ็นระบุว่าคำขอมาจาก weChat return tmpstr! = null? tmpstr.equals (signature.touppercase ()): false; - sha1:
/** * แพลตฟอร์มสาธารณะ WeChat (java) SDK * * sha1 อัลกอริทึม * @author Helijun 2016/06/15 19:49 */ชั้นเรียนสุดท้ายของสาธารณะ sha1 {ส่วนตัวคงที่ถ่านสุดท้าย [] hex_digits = {'0', '1', '2', '3' 'b', 'c', 'd', 'e', 'f'}; /*** ใช้ไบต์ดิบจากการย่อยและจัดรูปแบบให้ถูกต้อง * * @param ไบต์ไบต์ดิบจาก digest * @return ไบต์ที่จัดรูปแบบ */ สตริงคงที่ส่วนตัว getFormattedText (byte [] bytes) {int len = bytes.length; StringBuilder buf = new StringBuilder (len * 2); // แปลง ciphertext เป็นรูปแบบสตริง hexadecimal สำหรับ (int j = 0; j <len; j ++) {buf.append (hex_digits [(ไบต์ [j] >> 4) & 0x0f]); buf.append (hex_digits [bytes [j] & 0x0f]); } return buf.toString (); } String String สาธารณะเข้ารหัส (String str) {if (str == null) {return null; } ลอง {messageGeSest messageGeStest = messageGeSt.getInstance ("sha1"); messageGeSt.update (str.getBytes ()); กลับ getFormattedText (messageGeSt.digest ()); } catch (exception e) {โยน runtimeException ใหม่ (e); -เมื่อคุณส่งและบันทึกไว้บนแพลตฟอร์มสาธารณะและดู "ความสำเร็จในการเข้าถึง" Green Prompt "ขอแสดงความยินดีกับการเข้าถึง WeChat กระบวนการนี้ต้องใช้ความระมัดระวังมากขึ้นและให้ความสนใจกับคดีในอัลกอริทึมการเข้ารหัส หากการเข้าถึงไม่สำเร็จกรณีส่วนใหญ่เป็นปัญหาเกี่ยวกับอัลกอริทึมการเข้ารหัสให้ตรวจสอบเพิ่มเติม
4. ใช้บริการตอบกลับข้อความอัตโนมัติ
/ ** * คำขอกระบวนการจาก weChat * * @param Request * @return */ สตริงสาธารณะ weixinpost (คำขอ httpservletRequest) {สตริง respmessage = null; ลอง {// XML คำขอการแยกวิเคราะห์ <String, String> requestMap = MessageUtil.xmlTomap (คำขอ); // บัญชีผู้ส่ง (open_id) สตริง fromusername = requestmap.get ("fromusername"); // สตริงบัญชีสาธารณะ tousername = requestmap.get ("tousername"); // ประเภทข้อความสตริง msgtype = requestmap.get ("msgtype"); // ข้อความเนื้อหาสตริงเนื้อหา = requestmap.get ("เนื้อหา"); logger.info ("fromusername คือ:" + fromusername + ", tousername คือ:" + tousername + ", msgtype คือ:" + msgtype); // ข้อความถ้า (msgtype.equals (messageutil.req_message_type_text)) {// ที่นี่คุณเรียกใช้ตรรกะที่สอดคล้องกันตามคำหลักมีเพียงหนึ่งเดียวที่คุณคิดไม่ได้ text.setContent ("ข้อความคือ" + เนื้อหา); text.settousername (Fromusername); text.setFromusername (tousername); text.setCreateTime (วันที่ใหม่ (). getTime () + ""); text.setmsgtype (msgtype); respmessage = messageUtil.TextMessagetOxml (ข้อความ); }/*else ถ้า (msgtype.equals (messageUtil.req_message_type_event)) {// เหตุการณ์พุชสตริงเหตุการณ์ eventtype = requestmap.get ("เหตุการณ์"); // ประเภทเหตุการณ์ถ้า (EventType.equals Return Messageresponse.getTextMessage (FromUSERNAME, TOUSERNAME, RESPCONTENT); } อื่นถ้า (EventType.equals (MessageUtil.Event_Type_Click)) {// เมนูที่กำหนดเองคลิกสตริงเหตุการณ์ EventKey = requestMap.get ("EventKey"); // ค่าคีย์เหตุการณ์ที่สอดคล้องกับค่าคีย์ที่ระบุเมื่อสร้างเมนู menu ที่กำหนดเอง กลับ xxx; }} // เปิดการทดสอบการจดจำเสียง WeChat 2015-3-30 อื่น ๆ ถ้า (msgtype.equals ("เสียง")) {String recvMessage = requestmap.get ("การจดจำ"); // respcontent = "ผลการวิเคราะห์คำพูดที่ได้รับ:"+recvMessage; if (recvMessage! = null) {respcontent = tulingapiprocess.getTulingResult (recvMessage); } else {respcontent = "สิ่งที่คุณพูดนั้นคลุมเครือเกินไปคุณสามารถพูดได้อีกครั้ง?"; } return messageresponse.getTextMessage (FromUSername, tousername, respcontent); } // ฟังก์ชั่นการถ่ายภาพอื่น ๆ ถ้า (msgtype.equals ("pic_sysphoto")) {} else {return messageresponse.getTextMessage (Fromusername, tousername, "กลับไปที่ว่าง"); }*/ // เหตุการณ์ผลักดันอย่างอื่นถ้า (msgtype.equals (MessageUtil.req_message_type_event)) {String eventtype = requestmap.get ("เหตุการณ์"); // ประเภทเหตุการณ์ // สมัครสมาชิกถ้า (eventtype.equals text.setContent ("ยินดีต้อนรับสู่การติดตาม xxx"); text.settousername (Fromusername); text.setFromusername (tousername); text.setCreateTime (วันที่ใหม่ (). getTime () + ""); text.setmsgtype (messageutil.resp_message_type_text); respmessage = messageUtil.TextMessagetOxml (ข้อความ); } // สิ่งที่ต้องทำหลังจากยกเลิกการสมัครผู้ใช้ไม่สามารถรับข้อความที่ส่งโดยบัญชีอย่างเป็นทางการดังนั้นจึงไม่จำเป็นต้องตอบกลับข้อความอื่นถ้า (EventType.equals (MessageUtil.event_type_unsubsribe)) {// unsubscribe} // เมนูคลิกที่กำหนดเอง requestmap.get ("EventKey"); // ค่าคีย์เหตุการณ์สอดคล้องกับค่าคีย์ที่ระบุเมื่อสร้างเมนูที่กำหนดเองถ้า (EventKey.equals ("customer_telephone")) {textMessage text = new TextMessage (); text.setContent ("0755-86671980"); text.settousername (Fromusername); text.setFromusername (tousername); text.setCreateTime (วันที่ใหม่ (). getTime () + ""); text.setmsgtype (messageutil.resp_message_type_text); respmessage = messageUtil.TextMessagetOxml (ข้อความ); }}}} catch (exception e) {logger.error ("ข้อผิดพลาด ... ")} ส่งคืน respmessage; -รหัสถูกโพสต์ดังกล่าวข้างต้น ส่วนใหญ่มีความคิดเห็น หากคุณอ่านความหมายพื้นฐานหนึ่งครั้งคุณไม่จำเป็นต้องอธิบาย
มีสถานที่แห่งหนึ่งที่ต้องการความสนใจเป็นพิเศษ:
สีแดงจากชื่อชื่อและ tousername เป็นสิ่งที่ตรงกันข้ามซึ่งเป็นหนึ่งในข้อผิดพลาด ฉันจำได้ว่าฉันได้ปรับมันมาเป็นเวลานาน แต่มันก็ไม่ใช่ปัญหา แต่มันไม่ทำงาน ในที่สุดฉันก็ได้รับข้อความหลังจากเปลี่ยนสองสิ่งนี้! ในความเป็นจริงมันถูกต้องที่จะคิดเกี่ยวกับมัน เมื่อคุณกลับไปที่ WeChat Server บทบาทของคุณจะเปลี่ยนไปดังนั้นผู้ส่งและตัวรับสัญญาณจึงตรงกันข้ามอย่างแน่นอน
5. MessageUtil
Public Class MessageUtil { / *** ส่งคืนประเภทข้อความ: ข้อความ* / สตริงสุดท้ายคงที่สาธารณะ resp_message_type_text = "text"; / *** ส่งคืนประเภทข้อความ: เพลง*/ สตริงสุดท้ายคงที่ resp_message_type_music = "เพลง"; / *** ส่งคืนประเภทข้อความ: ข้อความกราฟิก*/ สตริงสุดท้ายคงที่สาธารณะ resp_message_type_news = "ข่าว"; / *** คำขอประเภทข้อความ: ข้อความ*/ สาธารณะคงที่สตริงสุดท้าย req_message_type_text = "text"; / *** ประเภทข้อความร้องขอ: ภาพ*/ สตริงสุดท้ายคงที่ req_message_type_image = "image"; / *** ประเภทข้อความร้องขอ: ลิงก์*/ สตริงสุดท้ายคงที่ req_message_type_link = "ลิงก์"; / *** ประเภทข้อความร้องขอ: ตำแหน่งทางภูมิศาสตร์*/ สตริงสุดท้ายคงที่ req_message_type_location = "ตำแหน่ง"; / *** ประเภทข้อความร้องขอ: เสียง*/ สตริงสุดท้ายคงที่ req_message_type_voice = "เสียง"; / ** * ประเภทข้อความร้องขอ: พุช */ สตริงสุดท้ายคงที่ req_message_type_event = "เหตุการณ์"; / ** * ประเภทเหตุการณ์: สมัครสมาชิก (สมัครสมาชิก) */ สตริงสุดท้ายคงที่ event_type_subscribe = "สมัครสมาชิก"; / ** * ประเภทเหตุการณ์: ยกเลิกการสมัคร (ยกเลิกการสมัคร) */ สตริงสุดท้ายคงที่สาธารณะ event_type_unsubscribe = "ยกเลิกการสมัคร"; / ** * ประเภทเหตุการณ์: คลิก (เมนูที่กำหนดเองคลิกเหตุการณ์) */ สตริงสุดท้ายคงที่ event_type_click = "คลิก"; -ที่นี่เพื่อให้โปรแกรมการอ่านและความยืดหยุ่นดีขึ้นฉันได้ทำการห่อหุ้มบางอย่างกำหนดค่าคงที่หลายค่าและห่อหุ้มพารามิเตอร์บางอย่างที่ส่งผ่านจาก WeChat ไปยังวัตถุถาวร Java Bean รหัสหลักอยู่ข้างบน มุ่งเน้นไปที่การแปลงระหว่าง XML และ MAP
ในความเป็นจริงปัญหานี้เกิดจาก WeChat โดยใช้การสื่อสาร XML และเรามักจะใช้ JSON ดังนั้นเราอาจรู้สึกอึดอัดเล็กน้อยในช่วงเวลาสั้น ๆ
1. Introduce Jar Package
<!-Parse XML-> <predency> <sdeperency> <sdeperency> <roupId> dom4j </groupId> <ratifactId> dom4j </artifactid> <cersion> 1.6.1 </version> </การพึ่งพา> <การพึ่งพา> <roupid> com.thoughtworks.xstream </groupid>
2.xml ถึงแผนที่วัตถุคอลเลกชัน
/ ** * xml ถึงแผนที่ * @param Request * @return * @throws ioexception */ @suppresswarnings ("unchecked") แผนที่คงที่สาธารณะ <สตริง, สตริง> xmltomap (httpservletrequest คำขอ saxReader reader = new SaxReader (); inputstream ins = null; ลอง {ins = request.getInputStream (); } catch (ioexception e1) {e1.printstacktrace (); } เอกสารเอกสาร = null; ลอง {doc = reader.read (ins); Element root = doc.getRootelement (); รายการ <Element> list = root.Elements (); สำหรับ (องค์ประกอบ e: รายการ) {map.put (e.getName (), e.getText ()); } กลับแผนที่; } catch (documentException e1) {e1.printStackTrace (); } ในที่สุด {ins.close (); } return null; - 3. แปลงวัตถุข้อความเป็น XML
/ ** * แปลงวัตถุข้อความเป็น xml * * @param textMessage ข้อความข้อความ * @return xml */ สตริงคงที่สตริงสาธารณะ textMessagetOxml (textMessage textMessage) {xstream xstream = ใหม่ xstream (); xstream.alias ("xml", textMessage.getClass ()); return xstream.toxml (textMessage); - จนถึงตอนนี้งานเสร็จสมบูรณ์ ในเวลานี้คุณสามารถลองส่ง "ทดสอบ" ในบัญชีอย่างเป็นทางการ คุณจะได้รับการตอบกลับ weChat "ข้อความคือการทดสอบ" นี่คือกระบวนการตอบกลับที่ทำในรหัสข้างต้น แน่นอนคุณสามารถใช้จินตนาการของคุณเพื่อทำทุกสิ่งที่คุณต้องการทำเช่นตอบกลับ 1 ตรวจสอบสภาพอากาศ 2 ตรวจสอบการละเมิด ฯลฯ ....
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น