【原創】配置微信服務器與內網穿透--轉載請註明出處

微信公衆號開發

在進行學習微信公衆號開發時,首先我們需要做好一些必須的準備。

1.具有一個自己的公衆號平臺,方便進行學習。

2.在網上找一款內網穿透器,進行內網穿透,接入微信開發。

3.有一個已經搭建好的Web項目。

1.申請微信公衆號

進行微信公衆號申請時,在下方地址進行申請即可,我們申請時可以根據自己的不同需求進行申請,選擇訂閱號或者服務號。企業號的開發模式和微信公衆號類似,但是必須由企業才能進行申請。

https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN

這裏不對申請做過多描述,按照表單填寫即可,很簡單。

2.使用內網穿透器進行內網穿透

免費的內網穿透器有很多,博主使用過的有花生殼和Ngrok,這裏推薦使用Ngrok,花生殼速度很慢,而且自身網站也有很多BUG。Ngrok的網站地址如下:

https://www.ngrok.cc/#down-client

申請註冊完成後,選擇登錄按鈕進行登錄,在左側選擇開通隧道,進入如下界面,選擇免費的版本。

 

選擇後進行隧道開通,可以將表單設置爲如下信息:

 

前置域名可以寫一個自己喜歡的域名,端口號要與本地服務器的端口號一致。隧道名稱可以隨便起,方便自己識別。

然後我們要去下載區進行下載windows版本的客戶端。下載完成後進行解壓,可以獲得到兩個文件夾,這裏我們只保留下面一個文件夾即可。

 

運行該文件夾下的腳本文件 Sunny-Ngrok啓動工具.bat之後,可以看到如下界面

 

在這裏我們可以輸入隧道Id,隧道Id可以在穿透器的管理界面獲得,即下方的隧道Id

隨後將隧道Id填寫腳本中,如果需要啓動多個隧道,則以逗號進行分割,啓動內網穿透器,不要關閉。

3.測試項目內網穿透

在項目的隧道編輯頁面可以找到如下前置域名

 

該域名爲與我們平時項目運行時的域名localhost:8080相同,後跟項目路徑即可。

我的項目訪問名直接配置的/,可以獲得如下界面:

 

測試接口訪問成功後,我們的準備工作就已經完成了。

4.連接微信公衆號

我們可以進入開發者工具---開發者文檔 進行查看如何進行URL的接入

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432

在開始開發--接入指南 中可以看到,在進行接入時,微信公衆號會向定義好的接口URL發送get請求,參數爲

signature

微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。

timestamp

時間戳

nonce

隨機數

echostr

隨機字符串

根據微信開發文檔所指出,我們可以通過對所獲得的參數進行加密處理進行校驗,如果成功則返回echostr參數,表示接入成功。這裏我們將直接返回該參數,不進行驗證。

然後進入項目,進行代碼編寫,創建一個SpringMVC的Servlet接口:

@RequestMapping("check.do")
@ResponseBody
public String checkInterface(String signature, String timestamp, String nonce,
                           String echostr, HttpServletResponse response) throws IOException {
    // 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗
    
System.out.println(echostr);
    return echostr;
}

接口編寫完成以後,我們可以在微信管理界面中,進行接入接口的配置。

我們登錄進入自己所申請的微信公衆號,在最下方的開發中,有一個 基本配置 按鈕,進入頁面,進行配置我們公衆號的一系列信息。

 

這裏爲了便於學習,採用了明文模式,即不對來往的消息進行加密處理。URL需要填寫我們進行接入微信公衆號的URL,token可以隨意填寫,識別驗證進行使用。EncodingAESKey使用隨機生成即可。

5.Access_token的獲取

Access_token是在微信開發中,常用的一個token參數,這個參數每天最多獲取2000次,且參數的有效期默認爲7200秒。我們可以通過以下接口進行獲取:

https://api.weixin.qq.com/cgi-bin/token

grant_type

獲取access_token填寫client_credential

appid

第三方用戶唯一憑證

secret

第三方用戶唯一憑證密鑰,即appsecret

該接口中,具有以上三個參數,其中grant_type直接填寫client_credential即可,後兩個參數可以在開發者配置中找到,如下圖所示

 

開發者密碼需要進行重置以後才能看到。看完開發者密碼以後,要注意保存,否則無法再次查看。我們在進行對微信公衆平臺的訪問時,需要通過httpClient進行。在添加httpClient的jar包到項目中以後,添加一個工具類:

 

package com.mender.mdoa.weixin.util;

import org.apache.http.HttpEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HttpUtil {

    /**
     * 發送get請求到指定的URl
     * @param url Url地址
     * @param params 參數列表
     * @return 返回的信息
     */
    public String sendGet(String url, Map<String, String> params){
        StringBuffer sbUrl = new StringBuffer(url);
        //1.使用默認的配置的httpclient
        CloseableHttpClient client = HttpClients.createDefault();
        //2.使用get方法
        if(params != null && params.size() != 0){
            Set<String> keys = params.keySet();
            sbUrl.append("?");
            for(String key : keys){
                sbUrl.append(key).append("=").append(params.get(key)).append("&");
            }
            sbUrl.substring(0,sbUrl.length() - 1);
        }
        System.out.println(sbUrl.toString());
        HttpGet httpGet = new HttpGet(sbUrl.toString());
        InputStream inputStream = null;
        CloseableHttpResponse response = null;
        return this.excute(httpGet);
    }

    /**
     * 發送post請求到指定的URl
     * @param url Url地址
     * @param params 參數列表
     * @return 返回的信息
     */
    public String sendPost(String url, Map<String, String> params) throws UnsupportedEncodingException {
        StringBuffer sbUrl = new StringBuffer(url);
        //1.使用默認的配置的httpclient
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(sbUrl.toString());
        if(params != null && params.size() > 0){
            List<BasicNameValuePair> paramList = new LinkedList<BasicNameValuePair>();
            Set<Map.Entry<String, String>> entrySet = params.entrySet();
            for(Map.Entry<String, String> entry : entrySet){
                paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"UTF-8");
            httpPost.setEntity(entity);
        }
        return this.excute(httpPost);
    }

    /**
     * 發送信息
     * @param request
     * @return
     */
    private String excute(HttpUriRequest request){
        InputStream inputStream = null;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            response = httpClient.execute(request);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity, "utf-8");
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

 

 

 

 

 

然後使用該工具類發送請求到微信的access_token獲取接口即可。

如下方代碼所示:

 

public static String getToken(){
    String url="https://api.weixin.qq.com/cgi-bin/token";
    Map<String, String> params = new HashMap<String, String>();
    params.put("grant_type","client_credential");
    params.put("appid","wx128a89fa44624819");
    params.put("secret","a6ac12b17e8ce4b611f50c0e99571855");
    HttpUtil httpUtil = new HttpUtil();
    String response = httpUtil.sendGet(url, params);
    System.out.println(response);
    return response;
}

 

該方法所返回的response字符串,就是一個包含了access_token的json串,從字符串中提取即可。

在這裏可能會出現一下異常提示

{"errcode":40164,"errmsg":"invalid ip XXX.10.XXX.XXX, not in whitelist hint: [.L7cCA0682nfo1]"}

這裏是因爲我們沒有將自己的ip地址設置到公衆號的ip地址白名單中,我們只需要將報錯信息中的ip複製,然後添加到 微信管理中心---開發配置---白名單 中即可。

6.Access_token過期?

Access_token過期以後會跑出一個異常編碼,編碼的信息可以在微信開發文檔中進行查看。因爲Access_token具有有效期,因此我們需要每隔一段時間進行一次獲取,Access_token在獲取到下一個以後,前一個仍然是有效的,可以使用的,因此在這裏建議使用Spring的定時任務進行獲取,時間週期設定在小於兩小時即可。

我們也可以通過如下代碼進行有效性的測試:

 

public static void main(String args[]) throws UnsupportedEncodingException {
    String token1 = getToken();
    String token2 = getToken();
    Gson gson = new Gson();
    Map<String, String> map = gson.fromJson(token1, HashMap.class);
    token1 = map.get("access_token");
    map = gson.fromJson(token2, HashMap.class);
    token2 = map.get("access_token");
    String address1 = getServerAddress(token1);
    String address2 = getServerAddress(token2);
    System.out.println(address1);
    System.out.println(address2);
}

public static String getToken(){
    String url="https://api.weixin.qq.com/cgi-bin/token";
    Map<String, String> params = new HashMap<String, String>();
    params.put("grant_type","client_credential");
    params.put("appid","wx128a89fa44624819");
    params.put("secret","a6ac12b17e8ce4b611f50c0e99571855");
    HttpUtil httpUtil = new HttpUtil();
    String response = httpUtil.sendGet(url, params);
    System.out.println(response);
    return response;
}

public static String getServerAddress(String token){
    String url="https://api.weixin.qq.com/cgi-bin/getcallbackip";
    Map<String, String> params = new HashMap<String, String>();
    params.put("access_token",token);
    HttpUtil httpUtil = new HttpUtil();
    String response = httpUtil.sendGet(url, params);
    System.out.println(response);
    return response;
}

 

 

 

 

 

先獲取了兩個access_token然後使用這兩個access_token來獲取微信的服務地址,最後我們就可以得到這個結果。這樣可以證明access_token是可以多次獲取,且在後一次獲取後,前一次依然有效的。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章