Spring Boot+微信公衆號開發Demo(源碼見文章最低端)

目錄

 

微信公衆號開發

1、微信公衆號簡單介紹

2、微信公衆號申請

3、開發模式啓用以及接口配置

4、消息以及消息處理的工具

5、各種消息的接收與響應

6、圖文消息

7、自定義菜單的創建以及菜單的相應

8、獲取用戶的網頁授權

9、碼雲開源源碼:


微信公衆號開發

1、微信公衆號簡單介紹

微信公衆號是開發者或商家在微信公衆平臺上申請的應用賬號,該帳號與QQ賬號互通,通過公衆號,商家可在微信平臺上實現和特定羣體的文字圖片語音視頻的全方位溝通、互動 。形成了一種主流的線上線下微信互動營銷方式。

2、微信公衆號申請

首先搜索進入微信公衆平臺,網址爲:https://mp.weixin.qq.com/

點擊立即註冊按鈕,開始註冊我們的微信公衆號,可以申請訂閱號,服務號,小程序,還有企業微信。

選擇好要註冊的微信平臺之後,進行相關的信息填寫就可以創建成功了。

我們作爲開發者,在微信開發的時候有些功能是需要服務號等等功能的,而我們個人申請的微信公衆號是不支持我們進行服務號的相關操作的,因此我們在這需要微信的測試號進行我們的一些相關功能的測試操作的。

微信測試公衆號申請網址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

這就是我們的測試公衆號,我們進行相關的微信公衆號測試,都要在這個基礎上進行測試的。

3、開發模式啓用以及接口配置

正式的微信公衆號是需要啓動開發者模式之後,我們開發者才能正式開發微信公衆號呢,但在我們的測試微信公衆號中,只需要進行相關的接口配置就可以了。

這裏需要填寫URL和Token兩個值。URL指的是能夠接收處理微信服務器發送GET/POST請求的地址,並且是已經存在的,現在就能夠在瀏覽器訪問到的地址,這就要求我們先把公衆帳號後臺處理程序開發好(至少應該完成了對GET請求的處理)並部署在公網服務器上。Token後面會詳細說明。

以下是我的鏈接微信服務器的代碼:

這樣之後,我們的程序打包,發佈到服務器上並運行,在微信公衆號上填寫url還有token進行鏈接測試即可。

4、消息以及消息處理的工具

最終我們寫完的所有消息的封裝結構爲:

下面進行的操作我們首先要在自己的spring boot的配置文件——pom.xml文件中添加相關的依賴:

<!-- xstream 採用開源框架xstream來實現Java類到xml的轉換-->

<dependency>

<groupId>com.thoughtworks.xstream</groupId>

<artifactId>xstream</artifactId>

<version>1.3.1</version>

</dependency>

<!--藉助於開源框架dom4j去解析xml-->

<dependency>

<groupId>dom4j</groupId>

<artifactId>dom4j</artifactId>

<version>1.6.1</version><!--$NO-MVN-MAN-VER$-->

</dependency>

 

如何解析請求的消息:微信服務器會將用戶的請求通過processRequest方法發送給我們,如下圖所示:

doPost方法有兩個參數,request中封裝了請求相關的所有內容,可以從request中取出微信服務器發來的消息;而通過response我們可以對接收到的消息進行響應,即發送消息。

那麼如何解析請求消息的問題也就轉化爲如何從request中得到微信服務器發送給我們的xml格式的消息了。這裏我們藉助於開源框架dom4j去解析xml(這裏使用的是dom4j-1.6.1.jar),然後將解析得到的結果存入HashMap。

那麼如何返回給微信服務器消息呢:這裏我們將採用開源框架xstream來實現Java類到xml的轉換。

下面是我的消息處理工具類:

 


/**
 * 消息工具類
 *
 * @author yulin
 * @Creat date 2018-7-17 14:39
 */
public class MessageUtil {

    /**
     * 返回消息類型:文本
     */
    public static final String RESP_MESSAGE_TYPE_TEXT = "text";

    /**
     * 返回消息類型:音樂
     */
    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";

    /**
     * 返回消息類型:圖文
     */
    public static final String RESP_MESSAGE_TYPE_NEWS = "news";

    /**
     * 請求消息類型:文本
     */
    public static final String REQ_MESSAGE_TYPE_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_LOCATION = "location";

    /**
     * 請求消息類型:音頻
     */
    public static final String REQ_MESSAGE_TYPE_VOICE = "voice";

    /**
     * 請求消息類型:推送
     */
    public static final String REQ_MESSAGE_TYPE_EVENT = "event";

    /**
     * 事件類型:subscribe(訂閱)
     */
    public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

    /**
     * 事件類型:unsubscribe(取消訂閱)
     */
    public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

    /**
     * 事件類型:CLICK(自定義菜單點擊事件)
     */
    public static final String EVENT_TYPE_CLICK = "CLICK";

    /**
     * 解析微信發來的請求(XML)
     *
     * @param request
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
        // 將解析結果存儲在HashMap中
        Map<String, String> map = new HashMap<String, String>();

        // 從request中取得輸入流
        InputStream inputStream = request.getInputStream();
        // 讀取輸入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(inputStream);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子節點
        List<Element> elementList = root.elements();

        // 遍歷所有子節點
        for (Element e : elementList)
            map.put(e.getName(), e.getText());

        // 釋放資源
        inputStream.close();
        inputStream = null;

        return map;
    }

    /**
     * 文本消息對象轉換成xml
     *
     * @param textMessage 文本消息對象
     * @return xml
     */
    public static String textMessageToXml(TextMessage textMessage) {
        xstream.alias("xml", textMessage.getClass());
        return xstream.toXML(textMessage);
    }

    /**
     * 音樂消息對象轉換成xml
     *
     * @param musicMessage 音樂消息對象
     * @return xml
     */
    public static String musicMessageToXml(MusicMessage musicMessage) {
        xstream.alias("xml", musicMessage.getClass());
        return xstream.toXML(musicMessage);
    }

    /**
     * 圖文消息對象轉換成xml
     *
     * @param newsMessage 圖文消息對象
     * @return xml
     */
    public static String newsMessageToXml(NewsMessage newsMessage) {
        xstream.alias("xml", newsMessage.getClass());
        xstream.alias("item", new Article().getClass());
        return xstream.toXML(newsMessage);
    }

    /**
     * 擴展xstream,使其支持CDATA塊
     *
     */
    private static XStream xstream = new XStream(new XppDriver() {
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {
                // 對所有xml節點的轉換都增加CDATA標記
                boolean cdata = true;

                @SuppressWarnings("unchecked")
                public void startNode(String name, Class clazz) {
                    super.startNode(name, clazz);
                }

                protected void writeText(QuickWriter writer, String text) {
                    if (cdata) {
                        writer.write("<![CDATA[");
                        writer.write(text);
                        writer.write("]]>");
                    } else {
                        writer.write(text);
                    }
                }
            };
        }
    });
    public static String initText(String toUserName, String fromUserName, String content){
        TextMessage text = new TextMessage();
        text.setFromUserName(toUserName);
        text.setToUserName(fromUserName);
        text.setMsgType(REQ_MESSAGE_TYPE_TEXT);
        text.setCreateTime(new Date().getTime());
        text.setContent(content);
        return textMessageToXml(text);
    }


}

 

5、各種消息的接收與響應

在前面第四點中已經說明到接收到微信服務器發給我們的消息的,這裏面說一下關於微信公衆平臺的核心處理類:

 

package com.b505.weixin.service;

import com.b505.weixin.message.req.TextMessage;
import com.b505.weixin.util.MessageUtil;

import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

/**
 * 描述:核心服務類
 * authro:yulin
 * Create date 2020-2-7 20:21
 */
public class CoreService {
    /**
     * 處理微信發來的請求
     * @param request
     * @return
     */
    public static String processRequest(HttpServletRequest request) {
        String respMessage = null;
        try {
            // 默認返回的文本消息內容
            String respContent = "請求處理異常,請稍候嘗試!";

            // xml請求解析
            Map<String, String> requestMap = MessageUtil.parseXml(request);

            // 發送方帳號(open_id)
            String fromUserName = requestMap.get("FromUserName");
            // 公衆帳號
            String toUserName = requestMap.get("ToUserName");
            // 消息類型
            String msgType = requestMap.get("MsgType");

            // 回覆文本消息
            TextMessage textMessage = new TextMessage();
            textMessage.setToUserName(fromUserName);
            textMessage.setFromUserName(toUserName);
            textMessage.setCreateTime(new Date().getTime());
            textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
            textMessage.setFuncFlag(0);

            // 文本消息
            if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
                //發送圖文消息
                respContent = "您發送的是文本消息!";
            }
            // 圖片消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
                respContent = "您發送的是圖片消息!";
            }
            // 地理位置消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
                respContent = "您發送的是地理位置消息!";
            }
            // 鏈接消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
                respContent = "您發送的是鏈接消息!";
            }
            // 音頻消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
                respContent = "您發送的是音頻消息!";
            }
            // 事件推送
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件類型
                String eventType = requestMap.get("Event");
                // 訂閱
                if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                    respContent = "謝謝您的關注!";
                }
                // 取消訂閱
                else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
                    // TODO 取消訂閱後用戶再收不到公衆號發送的消息,因此不需要回復消息
                }
                // 自定義菜單點擊事件
                else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
                    // TODO 自定義菜單權沒有開放,暫不處理該類消息
                }
            }

            textMessage.setContent(respContent);
            respMessage = MessageUtil.textMessageToXml(textMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return respMessage;
    }
}

 

6、圖文消息

圖文消息相關總結:

1)一定要給圖文消息的Url屬性賦值。不管是單圖文,還是多圖文,或者是不含圖片的圖文,都有可能會被用戶點擊。如果Url爲空,用戶點擊後將會打開一個空白頁面,這給用戶的體驗是非常差的;

 

2)只有單圖文的描述纔會顯示,多圖文的描述不會被顯示;

 

3)圖文消息的標題、描述中可以使用QQ表情和符號表情。合理地運用表情符號,會使得消息更加生動;

 

4)圖文消息的標題、描述中可以使用換行符。合理地使用換行符,會使得內容結構更加清晰;

 

5)圖文消息的標題、描述中不支持超文本鏈接(html的<a>標籤)。

 

6)圖文消息的鏈接、圖片鏈接可以使用外部域名下的資源。

 

7)使用指定大小的圖片。第一條圖文的圖片大小建議爲640*320,其他圖文的圖片大小建議爲80*80。如果使用的圖片太大,加載慢,而且耗流量;如果使用的圖片太小,顯示後會被拉伸,容易失真。

 

8)每條圖文消息的圖文建議控制在1-4條。這樣在絕大多數終端上一屏能夠顯示完,用戶掃一眼就能大概瞭解消息的主要內容,這樣最有可能促使用戶去點擊並閱讀。

 

借鑑https://blog.csdn.net/lyq8479/article/details/9393195

 

7、自定義菜單的創建以及菜單的相應

access_token是公衆號的全局唯一接口調用憑據,公衆號調用各接口時都需使用access_token。開發者需要進行妥善保存。access_token的存儲至少要保留512個字符空間。access_token的有效期目前爲2個小時,需定時刷新,重複獲取將導致上次獲取的access_token失效。

公衆平臺的API調用所需的access_token的使用及生成方式說明:

1、建議公衆號開發者使用中控服務器統一獲取和刷新access_token,其他業務邏輯服務器所使用的access_token均來自於該中控服務器,不應該各自去刷新,否則容易造成衝突,導致access_token覆蓋而影響業務;

2、目前access_token的有效期通過返回的expire_in來傳達,目前是7200秒之內的值。中控服務器需要根據這個有效時間提前去刷新新access_token。在刷新過程中,中控服務器可對外繼續輸出的老access_token,此時公衆平臺後臺會保證在5分鐘內,新老access_token都可用,這保證了第三方業務的平滑過渡;

3、access_token的有效時間可能會在未來有調整,所以中控服務器不僅需要內部定時主動刷新,還需要提供被動刷新access_token的接口,這樣便於業務服務器在API調用獲知access_token已超時的情況下,可以觸發access_token的刷新流程。

公衆號和小程序均可以使用AppID和AppSecret調用本接口來獲取access_token。AppID和AppSecret可在“微信公衆平臺-開發-基本配置”頁中獲得(需要已經成爲開發者,且帳號沒有異常狀態)。**調用接口時,請登錄“微信公衆平臺-開發-基本配置”提前將服務器IP地址添加到IP白名單中,點擊查看設置方法,否則將無法調用成功。**小程序無需配置IP白名單。

下面是如何獲取access_token的方法:

 

 

package com.b505.weixin.util;

import com.b505.weixin.pojo.AccessToken;
import com.b505.weixin.pojo.Menu;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;


/***
 * <p>b505信息科學研究所</p>
 * @Description 獲取jsapi的憑證票(網上這代碼可真坑人)
 * @author yulin
 * @Creat date 2018-11-30 13:23
 */
public class JsapiTicketUtil {

    private static Logger log = LoggerFactory.getLogger(JsapiTicketUtil.class);


    // 獲取access_token的接口地址(GET) 限2000(次/天)
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";



    // 菜單創建(POST) 限100(次/天)
    public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";

    /**
     * 創建菜單
     *
     * @param menu        菜單實例
     * @param accessToken 有效的access_token
     * @return 0表示成功,其他值表示失敗
     */
    public static int createMenu(Menu menu, String accessToken) {
        int result = 0;

        // 拼裝創建菜單的url
        String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
        // 將菜單對象轉換成json字符串
        String jsonMenu = JSONObject.fromObject(menu).toString();
        // 調用接口創建菜單
        JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);

        if (null != jsonObject) {
            if (0 != jsonObject.getInt("errcode")) {
                result = jsonObject.getInt("errcode");
                log.error("創建菜單失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }

        return result;
    }

    /***
     * 描述:創建按鈕專用!獲取accessToken
     * auhtor:yulin
     * Create date 2019-9-16 12:42
     * @return
     */
    public static String getAccessToken(){
        String appid="wx41c9f671d9c6355f";//應用ID
        String appSecret="bad1b7703b0195a7ba94001cc455d1e7";//(應用密鑰)
        String url ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+appSecret+"";
        String backData=JsapiTicketUtil.sendGet(url, "utf-8", 10000);
        String accessToken = (String) JSONObject.fromObject(backData).get("access_token");
        return accessToken;
    }

    /***
     * 模擬get請求
     * @param url
     * @param charset
     * @param timeout
     * @return
     */
    public static String sendGet(String url, String charset, int timeout)
    {
        String result = "";
        try
        {
            URL u = new URL(url);
            try
            {
                URLConnection conn = u.openConnection();
                conn.connect();
                conn.setConnectTimeout(timeout);
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
                String line="";
                while ((line = in.readLine()) != null)
                {

                    result = result + line;
                }
                in.close();
            } catch (IOException e) {
                return result;
            }
        }
        catch (MalformedURLException e)
        {
            return result;
        }

        return result;
    }


    /**
     * 發起https請求並獲取結果
     *
     * @param requestUrl    請求地址
     * @param requestMethod 請求方式(GET、POST)
     * @param outputStr     提交的數據
     * @return JSONObject(通過JSONObject.get(key)的方式獲取json對象的屬性值)
     */
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 創建SSLContext對象,並使用我們指定的信任管理器初始化
            TrustManager[] tm = { new My509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 從上述SSLContext對象中得到SSLSocketFactory對象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 設置請求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 當有數據需要提交時
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意編碼格式,防止中文亂碼
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 將返回的輸入流轉換成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 釋放資源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("Weixin server connection timed out.");
        } catch (Exception e) {
            log.error("https request error:{}", e);
        }
        return jsonObject;
    }



    /**
     * 獲取access_token
     *
     * @param appid 憑證
     * @param appsecret 密鑰
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret) {
        AccessToken accessToken = null;

        String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);

        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        // 如果請求成功
        if (null != jsonObject) {
            try {
                accessToken = new AccessToken();
                accessToken.setToken(jsonObject.getString("access_token"));
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
            } catch (JSONException e) {
                accessToken = null;
                // 獲取token失敗
                log.error("獲取token失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return accessToken;
    }


}

 

 

 

 

public static Menu getMenu() {

      CommonButton btn11 = new CommonButton();
      btn11.setName("主頁");
      btn11.setType("click");
      btn11.setKey("11");

      CommonButton btn21=new CommonButton();
      btn21.setName("會員通道");
      btn21.setType("click");
      btn21.setKey("21");

      CommonButton btn31=new CommonButton();
      btn31.setName("工作平臺");
      btn31.setType("view");
      btn31.setUrl("http://hyxw.work/servicefunctiontwo");

   /* CommonButton btn32=new CommonButton();
      btn32.setName("收費測試");
      btn32.setType("view");
      btn32.setUrl("https://mp.weixin.qq.com/s?__biz=MzIyNjIyNzk4OQ==&mid=2247483660&idx=1&sn=57914686073b68cf156fe647321b87bf&chksm=e872e376df056a6090791b63ace6e065a8681a7976e5e68289bf37aa5f09cb53507bb074bd6f&token=1850092517&lang=zh_CN#rd");
*/
/*     CommonButton btn32=new CommonButton();
      btn32.setName("用戶諮詢");
      btn32.setType("click");
      btn32.setKey( "32" );*/

      /*CommonButton btn33=new CommonButton();
      btn33.setName("聯繫方式");
      btn33.setType("click");
      btn33.setKey( "33" );*/

      ComplexButton mainBtn2=new ComplexButton();
      mainBtn2.setName("工作平臺");
      mainBtn2.setSub_button(new CommonButton[]{btn31});

      Menu menu = new Menu();
      menu.setButton(new Button[] {btn11, btn21,mainBtn2 });

      return menu;
   }

 

 

8、獲取用戶的網頁授權

 

 

/**
 * 描述:獲取微信用戶的網頁授權
 * 接口地址:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx41c9f671d9c6355f&redirect_uri=http%3a%2f%2f39.105.65.69%2ftext1&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
 * author:yulin
 * Create date 2020-2-21 12:22
 */
@RequestMapping("/text1")
public String text1(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {

    request.setCharacterEncoding("gb2312");
    response.setCharacterEncoding("gb2312");

    //用戶同意授權
    String code =request.getParameter("code");

    if(!"authdeny".equals(code)){


        WeixinOauth2Token weixinOauth2Token= AdvancedUtil.getOauth2AccessToken("","",code);
        //網頁授權接口訪問憑證
        String accessToken=weixinOauth2Token.getAccessToken();
        //用戶標識
        String openId=weixinOauth2Token.getOpenId();
        //獲取用戶信息
        SNSUserInfo snsUserInfo=AdvancedUtil.getSNSUserInfo(accessToken,openId);

        System.out.println("--------------------------------------------用戶的城市在"+snsUserInfo.getCity());


        return "text";
    }


    return "error1";

}

 

 

 

 

package com.b505.weixin.util;

import com.b505.weixin.pojo.SNSUserInfo;
import com.b505.weixin.pojo.WeixinOauth2Token;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;

public class AdvancedUtil {

    public static Logger logger = LoggerFactory.getLogger(AdvancedUtil.class);


    /**
     * 獲取網頁授權憑證
     * @param appId 公衆號的唯一標識
     * @param appSecret 公衆號的密匙
     * @param code
     * @return WeixinAouth2Token
     *
     */
    public static WeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code){

        WeixinOauth2Token wat=null;
        //拼接請求信息
        String requestUrl ="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

        requestUrl=requestUrl.replace("APPID",appId);
        requestUrl=requestUrl.replace("SECRET",appSecret);
        requestUrl=requestUrl.replace("CODE",code);
        //獲取網頁授權的憑證
        JSONObject jsonObject =JsapiTicketUtil.httpRequest(requestUrl,"GET",null);

        if(null!=jsonObject){

            try {
                wat=new WeixinOauth2Token();
                wat.setAccessToken(jsonObject.getString("access_token"));
                wat.setExpiresIn(jsonObject.getInt("expires_in"));
                wat.setRefreshToken(jsonObject.getString("refresh_token"));
                wat.setOpenId(jsonObject.getString("openid"));
                wat.setScope(jsonObject.getString("scope"));

            } catch (Exception e) {
                // TODO: handle exception
                wat=null;
                int errorCode=jsonObject.getInt("errcode");
                String errorMsg=jsonObject.getString("errmsg");
                logger.error("獲取網絡授權失敗  errcode:{} errmsg:{}",errorCode,errorMsg);

            }

        }
        return wat;
    }

    /**
     * 通過網頁授權獲取用戶的信息
     *
     * @param accessToken 網頁授權接口調用憑證
     * @param openId 用戶標識
     *
     */
    @SuppressWarnings({"deprecation","unchecked"})
    public static SNSUserInfo getSNSUserInfo(String accessToken, String openId){

        SNSUserInfo snsuserInfo=null;
        //拼接請求地址
        String requestUrl="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
        requestUrl =requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
        //通過網頁授權獲取用戶的信息
        JSONObject jsonObject=JsapiTicketUtil.httpRequest(requestUrl, "GET", null);
        if(null!=jsonObject){
            try {
                snsuserInfo=new SNSUserInfo();
                //用戶標識
                snsuserInfo.setOpenId(jsonObject.getString("openid"));
                //暱稱
                snsuserInfo.setNickname(jsonObject.getString("nickname"));
                //性別(1是男性 2是女性 0是未知)
                snsuserInfo.setSex(jsonObject.getInt("sex"));
                //用戶所在的國家
                snsuserInfo.setCountry(jsonObject.getString("country"));
                //用戶所在的省份
                snsuserInfo.setProvince(jsonObject.getString("province"));
                //用戶所在的城市
                snsuserInfo.setCity(jsonObject.getString("city"));
                //用戶頭像
                snsuserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
                //用戶特權信息
                snsuserInfo.setPrivilegeList(JSONArray.toList(jsonObject.getJSONArray("privilege"), List.class) );
                System.out.println("-----------------------------------------openid="+snsuserInfo.getOpenId());

            } catch (Exception e) {
                // TODO: handle exception
                snsuserInfo=null;
                int errorCode=jsonObject.getInt("errcode");
                String errorMsg=jsonObject.getString("errmsg");
                logger.error("獲取用戶信息失敗  errcode:{} errmsg:{}",errorCode,errorMsg);
            }
        }

        return snsuserInfo;
    }



}

 

 

9、碼雲開源源碼:

https://gitee.com/hyxw/wechat_learning/

 

 

 

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