公衆號簡介
微信公衆號有訂閱號、服務號、企業號,在註冊的時候看到這樣的信息,只有訂閱號可以個人申請,服務號和企業號要有企業資質纔可以。這裏所說的微信公衆號開發指的是訂閱號和服務號。
另外,未認證的個人訂閱號有一些接口是沒有權限的,並且目前個人訂閱號已不支持微信認證,也就是說個人訂閱號無法調用一些高級的權限接口,下圖就是一個未認證的個人訂閱號所具備權限列表,像生成二維碼、網頁授權、自定義菜單、微信支付這樣的接口權限都是不具備的。
說了半天,那如果沒有企業資質,又想做高級接口的開發怎麼辦呢。
微信公衆平臺提供了測試公衆賬號,登錄地址爲:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login,只需要到這個頁面,點擊登錄,並用自己的微信客戶端掃碼,並授權登錄,就可以獲得屬於自己的測試公衆號。測試公衆號具備幾乎所有的接口,平時開發如果沒有可用的公衆號,就用這個測試的公衆號就可以了。
本地測試環境搭建
開發微信公衆賬號的一大痛苦之處就是調試問題,每次實現一個功能後都需要部署到一個公網服務器,雖然目前有各種免費雲平臺可以部署,但是調式基本只能靠日誌輸出了,而且沒次修改->部署->查看日誌,這樣的操作過程非常浪費時間,時間就是生命,這樣難道不是在浪費生命嗎。那麼,有沒有辦法可以本地部署,本地調試呢?
當然有,因爲每次向公衆號發送一條指令,公衆號所在的服務器要和你的服務器進行網絡交互,所以說你的服務器要保證外網可以訪問到,那麼只需要將你本地映射到一個外網地址即可實現微信公衆號的本地調試。提供這樣功能的軟件不少,比如花生殼,但是要收費的。
=======================================================
本人使用的內網穿透工具是natapp,下面說一下大概的部署natapp的過程吧。
1、註冊賬號,生成隧道
在“購買隧道”那裏的免費隧道中,可以創建免費隧道,創建好後,可以在“我的隧道”頁面中看到,把authtoken記下來,下面用到。
2、下載客戶端,配置配置文件,啓動隧道
客戶端下載頁:https://natapp.cn/#download
本人用的是windows版本,下載好後,解壓。然後在解壓後的根目錄新建一個文件config.ini,內容如下(自己配置前面獲取到的隧道訪問token):
#將本文件放置於natapp同級目錄 程序將讀取 [default] 段
#在命令行參數模式如 natapp -authtoken=xxx 等相同參數將會覆蓋掉此配置
#命令行參數 -config= 可以指定任意config.ini文件
[default]
authtoken= #對應一條隧道的authtoken
clienttoken= #對應客戶端的clienttoken,將會忽略authtoken,若無請留空,
log=none #log 日誌文件,可指定本地文件, none=不做記錄,stdout=直接屏幕輸出 ,默認爲none
loglevel=ERROR #日誌等級 DEBUG, INFO, WARNING, ERROR 默認爲 DEBUG
http_proxy= #代理設置 如 http://10.123.10.10:3128 非代理上網用戶請務必留空
啓動客戶端,成功後如下:
可以看到域名 http://xxxx.natappfree.cc 映射到了 127.0.0.1:80
3、配置nginx反向代理
現在,隧道已經建立了,由於默認映射到本地的80端口,假設項目需要在8090端口訪問,這時需要部署nginx,nginx的部署如下,這裏是把http://xxxx.natappfree.cc 反向代理到 http:localhost:8090
#微信公衆號測試,反向代理映射到http://127.0.0.1:8190
server{
listen 80;
server_name xxxx.natappfree.cc;
location / {
proxy_pass http://127.0.0.1:8190;
root html;
index index.html index.htm;
#設置主機頭和客戶端真實地址,以便服務器獲取客戶端真實IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
部署nginx成功後,需要在項目中寫點代碼,作爲公衆號服務器校驗(在公衆號後臺添加服務器URL時,需要測試成功才能配置),校驗規則參考:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319
好了,看下接入校驗代碼吧。
/**
* 校驗信息是否是從微信服務器發出,處理消息
*
* @return
*/
@RequestMapping(value = {"", "/"}, method = {RequestMethod.GET})
public void connectWX(HttpServletRequest request, HttpServletResponse response) {
try {
String signature = request.getParameter("signature");
// 時間戳
String timestamp = request.getParameter("timestamp");
// 隨機數
String nonce = request.getParameter("nonce");
// 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗
if (SignUtils.checkSignature(signature, timestamp, nonce)) {
// 隨機字符串
String echostr = request.getParameter("echostr");
logger.info("接入成功,echostr=" + echostr);
response.getWriter().write(echostr);
} else {
logger.info("接入失敗,簽名校驗失敗");
}
} catch (Exception e) {
logger.error("接入失敗", e);
}
}
/**
* 簽名工具類
*/
public class SignUtils {
/**
* 驗證簽名
*
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[]{WechatConfig.WECHAT_TOKEN, timestamp, nonce};
// 將token、timestamp、nonce三個參數進行字典序排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 將三個參數字符串拼接成一個字符串進行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 將sha1加密後的字符串可與signature對比,標識該請求來源於微信
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
/**
* 將字節數組轉換爲十六進制字符串
*
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 將字節轉換爲十六進制字符串
*
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
爲了保守起見,先在瀏覽器訪問http://xxxx.natappfree.cc看下是否可以訪問本地的應用吧,OK之後繼續。
4、公衆號平臺配置服務器
自己在服務器配置中,填寫URL和TOKEN吧,如果微信公衆號使用GET請求訪問到了我們的服務器,並且獲取到了返回的報文,會配置成功。否則顯示配置失敗
至此,開發環境已經配置完畢。