微信公衆號,我們都很熟悉。但是如何開一個屬於自己的一個微信公衆號,其實很簡單。這邊文章就給一個簡單的例子。需要準備的環境:
1、域名,用於微信公衆號訪問我們的服務器,如沒有域名,建議使用花生殼進行內網穿透來訪問我們的項目(具體使用方法,不在這裏討論)
2、需要申請一個微信公衆號:https://mp.weixin.qq.com/
3、需要一個Javaweb項目
萬事俱備後,開始生路。
第一步,對微信公衆號的一些配置:
登錄微信公衆平臺,找到如圖所示
填寫如下的信息,url是我們項目的URL,token是我們自己定義的
此時,我們點提交會報錯,是因爲我們還沒有校驗,當我們點提交之後,會通過get方式發送一些校驗的數據到我們的項目。然後我們需要進行校驗
第二步,數據的檢驗,檢驗方式是SHA1算法,具體如下代碼
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
System.out.println("進入get方法");
String str = request.getQueryString();
String echostr = check(str);
OutputStream out = response.getOutputStream();
if(str != null)
{
try
{
out.write(echostr.getBytes());
}finally{
out.close();
}
}
}
private String check(String text)
{
//解析發過來的參數:
//signature=2e334555ebb6e43ec2c975d6ad54f642d7c95252&echostr=9019000808531292887×tamp=1563681495&nonce=1882518168
/*
* 微信公衆號會通過get請求發送如上的參數,然後我們驗證是否是微信公衆號的請求,
* timestamp nonce tokone 我們將這三個連起來進行加密,加密前要對他們進行按字母排序,
* 其中tokone是我們自己寫的
* 如果密文匹配,我們返回echostr的值,此時微信公衆化那邊就認爲匹配成功
*/
String[] content = text.split("&");
String signature = content[0].split("=")[1];
String echostr = content[1].split("=")[1];
String timestamp = content[2].split("=")[1];
String nonce = content[3].split("=")[1];
String token = "hello2019";//這個自己定義,單要與頁面上的一致
String[] arr = {token , timestamp , nonce};
Arrays.sort(arr);//根據字符的順序排序
//排序後將三個字符串連起來
String checkCode = arr[0] + arr[1] + arr[2];//將排序後字符串連接起來
MessageDigest md;
try
{
//進行SHA1加密
md = MessageDigest.getInstance("SHA1");
md.update(checkCode.getBytes());
byte[] code = md.digest();
//將加密後的字節數組轉成十六 進制字符串
String ss = Hex.encodeHexString(code);
if(ss.endsWith(signature))//判斷兩個密文是否一致
{
return echostr;
}
} catch (NoSuchAlgorithmException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
校驗通過之後,我點提交按鈕就會提示校驗成功。
第三步,處理文本信息。當我們檢驗成功之後,我們在公衆號好發一條消息,微信公衆號會通post方式以xml格式發送到我的項目,然後我們就對數據進行解析,具體各種字段的含義可以參考微信公衆號的開發文檔https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1472017492_58YV5
下面是我自己的處理方法,首先寫一個工具類,用來xml與map之間的轉換,其中用到dom4j的jar包,代碼如下:
package my;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class TextUtils
{
/**
* 讀取字符串
* @param input
* @return
* @throws IOException
*/
public static String readAsText(InputStream input , String charSet) throws IOException
{
ByteArrayOutputStream cache = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int count = -1;
while(true)
{
int n = input.read(buf);
if(n == 0)
{
try
{
Thread.sleep(3000);
count++;
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if(count < 3)
{
continue;
}
else
{
break;
}
}
if(n < 0)
{
break;
}
cache.write(buf, 0, n);
}
return cache.toString(charSet);
}
/**
* 默認編碼格式是UTF-8
* @param input
* @return
* @throws IOException
*/
public static String readAsText(InputStream input) throws IOException
{
return readAsText(input , "UTF-8");
}
/**
* 將xml格式轉成map
* @return
* @throws DocumentException
*/
public static Map<String , String> xml2Map(InputStream input) throws DocumentException
{
Map<String , String> map = new HashMap<String , String>();
SAXReader xmlReader = new SAXReader();
Document x_doc = xmlReader.read(input);
Element x_root = x_doc.getRootElement();
List<Element> list = x_root.elements();
for(Element e : list)
{
String name = e.getName();
String value = e.getTextTrim();
map.put(name, value);
}
return map;
}
/**
*
* @param map
* @return
* @throws IOException
*/
public static String map2Xml(Map<String , String> map) throws IOException
{
//創建一個空的Document
Document x_doc = DocumentHelper.createDocument();
//添加跟元素
Element x_root = x_doc.addElement("xml");
Iterator<java.util.Map.Entry<String, String>> entries = map.entrySet().iterator();
while(entries.hasNext())
{
Entry<String, String> entry = entries.next();
String key = entry.getKey();
Object value = entry.getValue();
x_root.addElement(key).addCDATA((String) value);
}
OutputStream out = new ByteArrayOutputStream();
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
format.setSuppressDeclaration(true);
format.setIndent(true);
format.setNewlines(true);
XMLWriter xmlWriter = new XMLWriter(out,format);
xmlWriter.write(x_doc);
xmlWriter.close();
return out.toString();
}
}
消息的接收與回覆:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
System.out.println("用戶發出信息");
InputStream input = request.getInputStream();
try
{
//將用戶發過來的信息轉成map
Map<String , String> map = TextUtils.xml2Map(input);
//獲取消息內容
String content = (String) map.get("Content");
//構造返回的信息
Map<String , String> reply = new HashMap();
reply.put("ToUserName", map.get("FromUserName"));
reply.put("FromUserName", map.get("ToUserName"));
reply.put("CreateTime", String.valueOf(System.currentTimeMillis()));
reply.put("MsgType", "text");
reply.put("Content", "歡迎");
String str = TextUtils.map2Xml(reply);//將回復的信息轉成xml格式的
//將信息發出去
OutputStream out = response.getOutputStream();
out.write(str.getBytes());
out.close();
} catch (DocumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
此例子只給出了文本信息的處理,其實對其他類型信息的處理也是大同小異,就不在累贅。具體的消息每個字段代表的含義可參考微信公衆開發平臺的開發文檔。最後也提供源碼:鏈接:https://pan.baidu.com/s/1dkRzEJqrn_MyVvz0RL2WAw
提取碼:ssdv
有不足之處,希望多多提出寶貴意見。