私はしばらくの間、フロントエンドの時間に忙しかったです。私は文書をゼロから読んで、多くの落とし穴を踏んでいます。私は最近それを経験しました。私はいくつかの要約を作成することを検討しました。また、関連するプロジェクトに取り組んでいる学生にも言及します。
実際、一度やった後、難しくないことがわかります。一般的なアイデアは、開発者が必要とするユーザーメッセージとイベントプッシュは、WeChatサーバーを介してリクエストを開始し、パブリックプラットフォームで構成したサーバーURLアドレスに転送します。 WeChatサーバーには、署名、タイムスタンプ、ノンセ、およびエコーストロートの4つのパラメーターが表示されます。サーバーは、パブリックプラットフォームで構成されたトークンとアップロードされたタイムスタンプをスプライスします。 NonceはSha1で暗号化され、署名と一致します。アクセスが成功していることを示すために、tureを返します。
1。パブリックプラットフォーム構成
2.コントローラー
@controller@requestmapping( "/wechat")publicclass wechatcontroller {@value( "$ {dnbx_token}")private string dnbx_token; private static final logger logger = loggerfactory.getLogger(wechatcontroller.class);@resourcewechatservice wechatservice @throws ioexception */@requestmapping(value = "/connect"、method = {requestmethod.get、requestmethod.post})@responsebodypublicvoid connectweixin(httpservletrequest request、httpservletResponse応答)IOExcectionをスローするrequest.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 signature timestamp = request.getParameter( "Timestamp"); request.getParameter( "echostr"); //ランダム文字列//署名をチェックして要求を確認します。検証が成功した場合は、その現状でechostrを返し、アクセスが成功したことを示します。それ以外の場合、アクセスに失敗します。 Response.getWriter()。write(echostr); } else {logger.error( "署名の検証に失敗しました!"); }} else {string respmessage = "例外メッセージ!"; try {respmessage = wechatservice.wexinpost(request); out.write(respmessage); logger.info( "sulcited"); logger.info( "to weixin server"+respmessage); weixin! "); }}} catch(Exception e){logger.error( "weixinサーバーを接続するのはエラーです。");} fullly {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 '3' 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 request parsing map <string、string> requestmap = messageutil.xmltomap(request); requestmap.get( "fromusername"); // publicアカウント文字列tousname = requestmap.get( "tousername"); //メッセージタイプ文字列sgtype = requestmap.get( "msgtype"); // message content content = requestmap.get( "content"); logger.info( " "、msgtype is:" + msgtype); //テキストメッセージif(msgtype.equals(messagutil.req_message_text)){//対応するロジックはキーワードに従って実行されます。想像できないものは1つだけです。 (content.equals( "xxx")){} //自動回答textmessage text = new textmessage(); text.setContent( "text is" + content); text.settousername(fromusername); text.setfromusername(tousername); ""); text.setmsgtype(msgtype); respmessage = messageutil.textmessagetoxml(text);}/*else if(msgtype.req_message_type_event)){// event push string eventtype = requestmap.get (eventType.equals(messageutil.event_type_subscribe)){// respcontent = "xxx公式アカウントに従うように歓迎!"; return messageresponse.getTextmessage(fromusername、tousname、respcontent); event String eventKey = requestMap.get("EventKey");// Event KEY value, corresponding to the KEY value specified when creating the custom menu logger.info("eventKey is:" +eventKey);return xxx;}}// Turn on WeChat sound recognition test 2015-3-30else if(msgType.equals("voice")){String recvMessage = requestMap.get( "認識"); // respcontent = "受信音声分析結果:"+recvmessage; if(recvmessage!= null){respcontent = tulingapiprocess.gettulingResult(recvmessage);} else {respcontent = "あなたが言ったことはあまりにも曖昧です、あなたはもう一度言いますか? } //写真関数else if(msgtype.equals( "pic_sysphoto")){} else {return messageresponse.getTextmessage(fromusername、tousername、 "return empty"); }*// event push elsh if(msgtype.equals(messageutil.req_message_type_event)){string eventtype = requestmap.get( "event"); // event Type // subscribe if(eventtype.equals(mesageutil.event_type_tepe_subscribure){texhmesseage textive = = mess textMessage(); text.setContent( "Welcome to follow、xxx"); text.settousername(fromusername); text.setfromusername(tousername); text.setcreatetime()。gettime() + "); text.setmsgtype(messageutil.resp_tyledage_type_text; messageutil.textmessagetoxml(text);} // todo登録解除後、ユーザーは公式アカウントから送信されたメッセージを受信できないため、メッセージに返信する必要はありません。 (eventType.equals(messageutil.event_type_click)){string eventkey = requestmap.get( "eventKey"); //イベントキー値、カスタムメニューを作成するときに指定されたキー値に対応するif(eventKey.equals( "Customer_telephone")){テキストテキストテキスト=新しいテキスト=新しいtextmessage(); text.setContent( "0755-86671980"); text.settousername(fromusername); text.set.setfromusername(tousername); text.setcreatetime(new Date()。gettime()。gettime() messageutil.textmessagetoxml(text);}}}}}} catch(exception e){logger.error( "error ...")} return Respmessage;}コードは上記のように投稿されています。それらのほとんどはコメントを持っています。基本的なセマンティクスを一度読んだ場合、説明する必要はありません。
簡単なアイデア:ユーザーが公式アカウントにメッセージを送信すると、WECHATサーバーは、XML形式で構成したサーバーの対応するインターフェイスへの投稿を介してユーザーメッセージを要求します。私たちがしなければならないことは、メッセージタイプなどに基づいて対応する論理処理を実行し、XML形式を介して最終的な返品結果をWeChatサーバーに返すことです。
特別な注意が必要な場所が1つあります。
UsernameとTousnameの赤い色はまったく逆ですが、これも落とし穴の1つです。私は長い間それを調整していたことを覚えていますが、それは問題ではありませんでしたが、うまくいきませんでした。最後に、これら2つを変更した後にメッセージを受け取りました!実際、それについて考えるのは正しいです。 WeChatサーバーに戻ると、役割が変更されるため、送信者と受信機は間違いなく反対です。
5.messageutil
public class messageutil {/ ***メッセージタイプを返します*/ public static final string resp_message_type_text = "text"; / *** returnメッセージタイプ:音楽*/ 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.ジャーパッケージを紹介します
<! - xml-> <dependency> dom4j </groupid> <artifactid> dom4j </artifactid> <version> 1.6.1 </version> </dependency> <dependency> <groupid> com.thoughtworks.xstream </groupid> <artifactid>
2.xmlコレクションオブジェクトをマップします
/*** xml @param request* @return* @throws ioexception*/ @suppresswarnings( "unchecked")public static Map <String、string> xmltomap(httpservletrequest request)Throws ioexception {map <string> string = new hashmap <string> inexreder> = null; try {ins = request.getInputStream();} catch(ioException e1){e1.printstacktrace();} document doc = null; try {doc = reader.read(ins); element root = doc.getRotelement(); e.getText());} return map;} catch(documentException e1){e1.printstacktrace();} fullly {ins.close();} return 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.toxml();上記は、springmvc wechatアクセスを実装し、簡単な自動応答関数を実装するためのJavaの編集者の紹介です。私はそれが誰にでも役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は、すべての人に時間内に返信します。 wulin.comのウェブサイトへのご支援ありがとうございます!