私はしばらく前に忙しかった。私はWeChatの公式アカウントを開発し始め、文書をゼロから読み始めました。私は多くの落とし穴に踏み込んだ。私はそれを経験しました。私は最近、いくつかの要約を作成することを検討しました。また、関連するプロジェクトに取り組んでいる学生にも言及します。
1。アイデア
WeChat Access:開発者が必要とするユーザーメッセージとイベントプッシュは、WeChatサーバーを介してリクエストを開始し、パブリックプラットフォームで構成したサーバーURLアドレスに転送します。 WECHATサーバーは、署名、タイムスタンプ、ノンセ、およびエコーストアの4つのパラメーターを提供します。当社のサーバーは、パブリックプラットフォームで構成されたトークンとアップロードされたタイムスタンプをスプライブし、nonceはsha1で暗号化され、署名と一致します。アクセスが成功していることを示すために、tureを返します。
メッセージ返信:ユーザーが公式アカウントにメッセージを送信すると、WeChatサーバーは、XML形式で構成したサーバーの対応するインターフェイスに投稿を介してユーザーメッセージを要求します。私たちがしなければならないことは、メッセージタイプなどに基づいて対応する論理処理を実行し、XML形式を介して最終的な返品結果をWeChatサーバーに返すことです。WeChatパーティはそれをユーザーに伝えます。
1。パブリックプラットフォーム構成
2.コントローラー
@controller @requestMapping( "/wechat")publicclass wechatcontroller {@value( "$ {dnbx_token}")private string 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 reliesce) UTF-8(中国語の文字盤を防ぐ)リクエスト。SetchAracterEncoding( "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 signature string timestamp = request.getParameter( "Timestamp"); // Timestamp String nonce = request.getParameter( "nonce"); //ランダム数文字列echostr = request.getParameter サイン。検証が成功した場合は、その現状でechostrを返し、アクセスが成功したことを示します。それ以外の場合、アクセスに失敗します。 Response.getWriter()。write(echostr); } else {logger.error( "署名の検証に失敗しました!"); }} else {string respmessage = "例外メッセージ!"; try {respmessage = wechatservice.weixinpost(request); out.write(respmessage); logger.info( "要求が正常に完了した"); logger.info( "to weixin server"+respmessage); } catch(Exception e){logger.error( "メッセージをWeixinから変換できなかった!"); }}} catch(Exception e){logger.error( "weixinサーバーを接続するのはエラーです。"); }最後に{out.close(); }}}3。署名検証チェック署名
上記のコントローラーから、CheckSignatureと呼ばれるツールクラスのSignutilをカプセル化し、DNBX_TOKEN、署名、タイムスタンプ、NONCEの4つの値で渡されたことがわかります。このプロセスは非常に重要です。実際、WeChatによって送信された値の暗号化と復号化プロセスとしてそれを理解できます。セキュリティを確保するために、多くの大規模プロジェクトのすべてのインターフェイスには、このような検証プロセスがあります。 dnbx_token wechatパブリックプラットフォームでトークン文字列を構成しました。アイデアを秘密にしてください!他の3つは、GETリクエストを送信するためにWECHATサーバーから送信されたパラメーターです。 SHA1暗号化の層を実行します。
パブリッククラスSignutil { / ***検証署名* @paramトークンWechat Serverトークン、env.Propertiesファイルで構成され、開発者センターで構成されている必要があります* @param署名はsha1暗号化された証明書署名* @param timestamp timestamp* @param nonce nonce sintic sintic sintic booow sing sintic sing sing signature* @return string timestamp、string nonce){string [] arr = new String [] {token、Timestamp、nonce}; //トークン、タイムスタンプ、およびノンセの辞書順序を並べ替えます。 // 3つのパラメーター文字列を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 {] hex_digits = {'0'、 '1'、 '2' 3 '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]); } buf.toString();を返します。 } public static string encode(string str){if(str == null){return null; } try {MESSAGEDGEST MESSAGEDGEST = MESSAGEDGEST.GETINSTANCE( "SHA1"); MESSAGEDGEST.UPDATE(str.getBytes()); return getFormattedText(MESSAGEDGEST.DIGEST()); } catch(Exception e){新しいruntimeException(e); }}}パブリックプラットフォームに送信して保存し、グリーンプロンプトの「アクセス成功」を確認すると、WeChatアクセスの完了をおめでとうございます。このプロセスには、もう少し注意が必要であり、暗号化アルゴリズムのケースに注意を払う必要があります。アクセスが成功していない場合、ほとんどのケースは暗号化アルゴリズムの問題です。もっと確認してください。
4.自動メッセージ返信サービスを実装します
/ ** * wechatからのプロセスリクエスト * * @param request * @return */ public string weixinpost(httpservletrequest request){string respmessage = null; try {// xml要求マップ<string、string> requestmap = messageutil.xmltomap(request); // senderアカウント(open_id)string fromusername = requestmap.get( "fromusername"); //パブリックアカウント文字列toushername = requestmap.get( "tousername"); //メッセージタイプ文字列msgtype = requestmap.get( "msgtype"); //メッセージコンテンツ文字列content = requestmap.get( "content"); logger.info( "fromusername is:" + fromusername + "、tousname is:" + tousername + "、msgtype is:" + msgtype); //テキストメッセージ(msgtype.equals(messageutil.req_message_text)){//ここで、キーワードに従って対応するロジックを実行すると、考えられないものは1つだけです。 text.setContent( "テキストは" + content); text.settousername(fromusername); text.setfromUsername(tousername); text.setcreatetime(new date()。getTime() + ""); text.setmsgtype(msgtype); respmessage = messageutil.textmessagetoxml(text); }/*else if(msgtype.equals(messageutil.req_message_type_type_type_event)){// event push string eventtype = requestmap.get( "event"); //イベントタイプif(eventytil.event_type_subscribe)){wakepcribe to supccribe to supccribe to supccribe to sufccribe to(messagutil.event_type_subscribe) return messageresponse.getTextMessage(fromusername、tousername、respcontent); } else if(eventType.equals(messageutil.event_type_click)){//カスタムメニュークリックイベント文字列eventKey = requestMap.get( "eventKey"); //イベントキー値。 xxxを返します。 }} // wechatサウンド認識テスト2015-3-30 else if(msgtype.equals( "Voice")){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 empt"); }*/ //イベントプッシュelse if(msgtype.equals(messageutil.req_message_type_event)){string eventtype = requestmap.get( "event"); // event type // subscribe if(eventtype.equals(mesageutil.event_type_tepe_texege){textmessage = texhmessage = message(); text.setContent( "Welcome follow、xxx"); text.settousername(fromusername); text.setfromUsername(tousername); text.setcreatetime(new date()。getTime() + ""); text.setmsgtype(messageutil.resp_message_type_text); respmessage = messageutil.textmessagetoxml(text); } // dodo登録解除後、ユーザーは公式アカウントから送信されたメッセージを受信できないため、メッセージに返信する必要はありません。 requestmap.get( "eventKey"); //イベントキー値は、カスタムメニューを作成するときに指定されたキー値に対応します(eventKey.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(text); }}}} catch(Exception e){logger.error( "error ...")} return respmessage; }コードは上記のように投稿されています。それらのほとんどはコメントを持っています。基本的なセマンティクスを一度読んだ場合、説明する必要はありません。
特別な注意が必要な場所が1つあります。
UsernameとTousnameの赤い色はまったく逆ですが、これも落とし穴の1つです。私は長い間それを調整していたことを覚えていますが、それは問題ではありませんでしたが、うまくいきませんでした。最後に、これら2つを変更した後にメッセージを受け取りました!実際、それについて考えるのは正しいです。 WeChatサーバーに戻ると、役割が変更されるため、送信者と受信機は間違いなく反対です。
5.messageutil
public class messageutil { / ***メッセージタイプを返します* / public static final string resp_message_type_text = "text"; / *** return message type:music*/ public static final string resp_message_type_music = "music"; / *** returnメッセージタイプ:グラフィックテキスト*/ public static final string resp_message_type_news = "news"; / ***メッセージタイプ:テキスト:テキスト*/ public static final string req_message_text = "text"; / ***メッセージタイプを要求します*/ 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_event = "event"; / ** *イベントタイプ:subscribe(subscribe) */ public static final string event_type_subscribe = "subscribe"; / ** *イベントタイプ:unsubscribe(unsubscribe) */ public static final string event_type_unsubscribe = "unsubscribe"; / ** *イベントタイプ:クリック(カスタムメニュークリックイベント) */ public static final string event_type_click = "click"; }ここでは、プログラムの読みやすさとスケーラビリティを改善するために、いくつかのカプセル化を行い、いくつかの定数を定義し、WeChatからJava Beanの永続オブジェクトに渡されたいくつかのパラメーターをカプセル化しました。コアコードは上記の通りです。 XMLとMAP間の変換に焦点を当てます
実際、この問題はXML通信を使用してWeChatに起因しており、通常はJSONを使用しているため、短期間で少し不快に感じるかもしれません。
1.ジャーパッケージを紹介します
<! - parse xml-> <dependency> dom4j </groupid> <artifactid> dom4j </artifactid> <version> 1.6.1 </version> </dependency> <dependency> <groupid> com.thoughtworks.xstream </groupid> <artifactid>
2.xmlコレクションオブジェクトをマップします
/ ** * XML TO MAP * @Param Request * @return * @Throws IOException */ @SuppressWarnings( "Un -checked")public static Map <String、String> xmltomap(httpservletrequest request)Throws ioexception {Map <String、String> Map = New Hashmap <String>); saxreader reader = new Saxreader(); inputstream ins = null; try {ins = request.getInputStream(); } catch(ioexception e1){e1.printstacktrace(); } document doc = null; try {doc = reader.read(ins);要素root = doc.getRootelement();リスト<要素> list = root.Elements(); for(要素e:list){map.put(e.getname()、e.getText()); }マップを返します。 } catch(documentexception e1){e1.printstacktrace(); }最後に{ins.close(); } nullを返します。 } 3。テキストメッセージオブジェクトをXMLに変換します
/ ** *テキストメッセージオブジェクトをXMLに変換 * * @Param TextMessage Text Message Object * @return XML */ public Static String textmessagetoxml(textMessage TextMessage){XStream XStream = new XStream(); Xstream.alias( "xml"、textmessage.getClass()); xstream.toxml(textmessage)を返します。 }これまでのところ、作業は完了しています。現時点では、公式アカウントで「テスト」を送信しようとすることができます。 WeChatの返信「テキストはテストです」を受け取ります。これは、上記のコードで作成された返信プロセスでもあります。もちろん、あなたの想像力を使って、天気をチェックする1、違反のチェックなど、あなたがやりたいことすべてをすることもできます。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。