微信公眾號開發:獲取openId和用戶信息


  • title: 微信公眾號開發:獲取openId和用戶信息
  • tags: 微信公眾號
  • categories: 筆記
  • date: 2017-05-01 14:35:34

最近一直在做微信公眾號項目的開發,會有一種感覺,就是微信相關的開發真TM的啰嗦麻煩啊。當首次接觸這個微信相關內容的開發時候,需要按照其官方文檔一步一步的按部就班,按照他的要求去操作。若是中途需要什么其他的開發資質或者權限,還要進行申請,不僅要花錢,重點還特么的很花時間,直接來幾個工作日,我暈菜了。。不過多吐槽一句,微信這邊的跟阿里云平臺那邊處理速度,真的差太遠了~~
不過,若是有一次的微信開發經驗,我相信日后再次進行微信相關內容的開發就不會有什么難度了,只要不在申請微信七七八八的東西上面花費太多時間就好了。(方式多種,符合微信官方規范即可,此處僅作參考)

image

要進行微信公眾號開發,那么要申請一個微信公眾號就必不可少了。現在微信公眾號類型有這幾種:訂閱號,企業號,服務號。關于三者的差別和介紹可以參考微信公眾號官網微信公眾平臺。申請通過之后,就能登陸微信公眾平臺管理平臺進行開發設置了。

每個公眾號申請成功后,微信服務那邊就會給每個公眾號分配一個與公眾號唯一性綁定的APPID。結合我們公眾平臺自己生成的密鑰,兩者就可以唯一確定某個公眾號以及是否合法了。接下來就應該參照微信公眾平臺開發文檔來進行開發前的配置設置。

開發前服務器配置

按照文檔所說,接入微信公眾平臺開發,開發者需要按照如下步驟完成:

1. 填寫服務器配置
2. 驗證服務器地址的有效性
3. 依據接口文檔實現業務邏輯

接下來就上述每個步驟進行說明好了。

(1) 填寫服務器配置
在申請成功公眾號后,登入web微信公眾號管理平臺,在管理平臺首頁左邊的導航欄選擇: 開發 --> 基本配置。就會進入改公眾號的開發基本配置管理。就可以看到有個區域是服務器配置,這個服務器配置,就是填寫我們將開發測試完成后的項目部署所在的服務器,且要填寫已經備案后域名地址(若是要進行微信支付開發)。

image

在填寫完所有服務器配置信息后,點擊提交,那么微信服務器會發送一個GET請求到我們上述URL填寫的地址上,我們服務器上通過接收微信服務器發送請求進行按照某種規則進行處理,將得到的結果返回微信服務器,進行判斷我們的服務器是否通過校驗,那么我們服務器上的代碼要如何處理這個校驗請求呢,往下看。

(2) 驗證服務器地址的有效性:
開發者提交信息后,微信服務器將發送GET請求到填寫的服務器地址URL上,GET請求攜帶四個參數:

參數          描述
signature   微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。
timestamp   時間戳
nonce       隨機數
echostr     隨機字符串

開發者通過檢驗signature對請求進行校驗,若確定此次GET請求來著微信服務器,請原樣返回echostr參數內容,則接入生效,成為開發者成功,否則接入失敗。(這一步也就是向微信服務器說明,上述我們配置的服務器確實是我們項目所在服務器,在接下來的開發,測試過程中,都會在外網的這個服務器上進行,微信那邊會認為是合法的)

加密/校驗流程如下:
1. 將token、timestamp、nonce三個參數進行字典序排序
2. 將三個參數字符串拼接成一個字符串進行sha1加密
3. 開發者獲得加密后的字符串可與signature對比,標識該請求來源于微信

好了,來看看我們在java后臺中,如何對微信這個請求進行處理的:結合上圖的URL地址,會通過springmvc被路由派發到指定類的指定方法中進行處理。

@Controller(value="WXConfigUtil")
@Qualifier(value="WXConfigUtil")
@RequestMapping(value="/wXConfigUtil")
public class WXConfigUtil{
    
    //這個token要與公眾平臺服務器配置填寫的token一致
    private final static String token = "wechat";
    private Log log = LogFactory.getLog(WXConfigUtil.class);
    
    @RequestMapping(value="/WXConfig",method=RequestMethod.GET)
    @ResponseBody
    public String verifyWXConfig(@RequestParam(value="signature",required=false) String signature,
                                    @RequestParam(value="timestamp",required=false) String timestamp,
                                    @RequestParam(value="nonce",required=false) String nonce,
                                    @RequestParam(value="echostr",required=false) String echostr) {
        System.out.println(" PARAM VAL: >>>" + signature + "\t" + timestamp + "\t" + nonce + "\t" + echostr);
        log.info("開始簽名驗證:"+" PARAM VAL: >>>" + signature + "\t" + timestamp + "\t" + nonce + "\t" + echostr);
        if (StringUtils.isNotEmpty(signature) && StringUtils.isNotEmpty(timestamp)
                &&StringUtils.isNotEmpty(nonce) && StringUtils.isNotEmpty(echostr)) {
            String sTempStr = "";
            try {
                sTempStr = SHA1.getSHA1(timestamp, nonce, token, "");
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isNotEmpty(sTempStr) && StringUtils.equals(signature, sTempStr)) {
                log.info("驗證成功:-----------:"+sTempStr);
                return echostr;
            } else {
                log.info("驗證失敗:-----------:00000");
                return "-1";
            }
        } else {
            log.info("驗證失敗:-----------:11111");
            return "-1";
        }
    }
    

通過校驗后,會在公眾號的服務器配置頁面有提示的,通過校驗后,后面就可以在此服務器上進行開發與測試了。
(3)依據接口文檔實現業務邏輯
用戶向公眾號發送消息時,公眾號方收到的消息發送者是一個OpenID,是使用用戶微信號加密后的結果,每個用戶對每個公眾號有一個唯一的OpenID。

此外,由于開發者經常有需在多個平臺(移動應用、網站、公眾帳號)之間共通用戶帳號,統一帳號體系的需求,微信開放平臺(open.weixin.qq.com)提供了UnionID機制。開發者可通過OpenID來獲取用戶基本信息,而如果開發者擁有多個應用(移動應用、網站應用和公眾帳號,公眾帳號只有在被綁定到微信開放平臺帳號下后,才會獲取UnionID),可通過獲取用戶基本信息中的UnionID來區分用戶的唯一性,因為只要是同一個微信開放平臺帳號下的移動應用、網站應用和公眾帳號,用戶的UnionID是唯一的。換句話說,同一用戶,對同一個微信開放平臺帳號下的不同應用,UnionID是相同的。詳情請在微信開放平臺的資源中心-移動應用開發-微信登錄-授權關系接口調用指引-獲取用戶個人信息(UnionID機制)中查看。

網頁授權獲取用戶基本信息

如果用戶在微信客戶端中訪問第三方網頁,這個場景就是在我們公眾號中通過菜單或者其他連接地址訪問我們自己開發的三方網頁,公眾號可以通過微信網頁授權機制來獲取用戶基本信息,從而實現業務邏輯。詳情參考:網頁授權獲取用戶基本信息

微信對于這個微信用戶訪問的三方頁面的授權是通過OAuth2.0鑒權的,現在很普遍的一個用戶授權機制。在官方文檔中有說明,若是需要在網頁中授權操作,那么需要填寫配置授權回調域名。僅僅是填寫一個不帶http或者https的域名字符串。該授權回調域名會在下面的網頁授權過程中,重定向的時候進行域名校驗。若是不填寫,或者填寫有誤,則網頁授權接口調用會失敗。

在微信公眾號管理平臺首頁中,點擊左邊導航欄:"設置" ---> "公眾號設置" --->"功能設置"。就會看到包括圖片水印,業務域名,JS接口安全域名,網頁授權域名。我們要設置的就是網頁授權回調域名,點擊網頁授權域名欄的設置按鈕,進行域名設置:
(例如直接寫 wx.example.com)

image

只是需要下載圖片上的一個text文件,上傳到服務器指定位置,能通過url直接訪問,讓微信服務器可以訪問進行字符串對比校驗即可,配置成功。

在微信客戶端的網頁開發的授權中,有兩種授權范圍scope:snsapi_basesnsapi_userinfo

1、以snsapi_base為scope發起的網頁授權,是用來獲取進入頁面的用戶的openid的,并且是靜默授權并自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁(往往是業務頁面)
2、以snsapi_userinfo為scope發起的網頁授權,是用來獲取用戶的基本信息的。但這種授權需要用戶手動同意,并且由于用戶同意過,所以無須關注,就可在授權后獲取該用戶的基本信息。
3、用戶管理類接口中的“獲取用戶基本信息接口”,是在用戶和公眾號產生消息交互或關注后事件推送后,
才能根據用戶OpenID來獲取用戶基本信息。這個接口,包括其他微信接口,都是需要該用戶(即openid)關注了公眾號后,才能調用成功的。

可以看到,在微信公眾號開發中,對與獲取微信用戶信息其實是有幾種不同的方式的。分別針對不同的實際場景下,若是要獲取的微信用戶并沒有關注我們的公眾號,我們只能通過網頁授權auth2.0,來讓頁面顯示提示獲取用戶信息,讓用戶來決定是否同意讓我們公眾號來獲取他信息;另一方面,若是微信用戶已經關注我們的公眾號話,我們就有權限直接通過指定接口獲取用戶信息,而無需讓用戶授權。

下面來說說通過網頁授權方式,獲取未關注公眾號的微信用戶信息。

snsapi_base

這個授權叫"靜默授權",意思就是在用戶打開我們開發的三方網頁頁面的時候,并不會顯示的彈出一個授權頁面,讓用戶知道要授權。而是進入頁面就默認可以獲取用戶的openId。這個靜默授權僅僅只能拿到微信用戶的openId就結束了。

(1) 獲取code
必須是在微信客戶端,引導微信用戶訪問下面文檔指定的url。注意,我們可以修改的僅僅是接口中重定向redirect_uri部分,可以重定向到我們自己開發的頁面中。這里要注意的是:<font color="red">這個重定向的url,跳轉回調redirect_uri必須要經過URLEncoder編碼</font>。

參考鏈接(請在微信客戶端中打開此鏈接體驗)
Scope為snsapi_base
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387
&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60
&response_type=code&scope=snsapi_base&state=123#wechat_redirect

看看在java項目中,如何進行這個操作:

    @RequestMapping(value="/routerToMyPage.html",method=RequestMethod.GET)
    public void redirectToMyPage(HttpServletRequest request,HttpServletResponse response){
        StringBuffer sb = new StringBuffer();
        StringBuffer encodeUrl = new StringBuffer(300);
        //公眾號中配置的回調域名(網頁授權回調域名)
        String doname = ConfigService.getValue("DONAME", "doname");
        String root = request.getContextPath();
        String appId = Constants.APPID;

        sb.append("https://open.weixin.qq.com/connect/oauth2/authorize?appid=");
        sb.append(appId);
        String url = "";
        try {
            //對重定向url進行編碼,官方文檔要求
            encodeUrl.append(doname).append(root).append("/my/myPage.html");
//          url = URLEncoder.encode(encodeUrl.toString(), "utf-8");
            url = URLEncoder.encode("https://domain/xbdWXBG(項目名稱)/my/myPage.html", "utf-8");
            sb.append("&redirect_uri=").append(url);
            //網頁授權的靜默授權snsapi_base
            sb.append("&response_type=code&scope=snsapi_base&state=123#wechat_redirect");
            response.sendRedirect(sb.toString());
        } catch (UnsupportedEncodingException e) {
            log.error("重定向url編碼失敗:>>" + e.getMessage());   
            e.printStackTrace();
        } catch (Exception e) {
            log.error("response重定向失敗:>>" + e.getMessage());   
            e.printStackTrace();
        }
    }

在上述代碼中,當用戶進入到routerToMyPage.html頁面進行請求,那么就能通過回調uri進行我們其他的頁面中,就能拿到code。因為在跳轉到重定向頁面過程中,微信服務器會將一個請求參數code值攜帶在請求url中。

(2) 得到openId
在靜默授權的第(1)步中,頁面會攜帶code參數,重定向跳轉到myPage.html頁面中,那么我們就可以在這個頁面中獲取code的值,并根據該值調用指定接口獲得當前微信用戶的openId。

    @RequestMapping(value="/myPage.html",method=RequestMethod.GET)
    public ModelAndView toMyPage(HttpServletRequest request,HttpServletResponse response){
        ....
        
        ModelAndView mv = new ModelAndView("/mypage/mypage");
        //獲取重定向攜帶的code參數值
        String code = request.getParameter("code");

        Object openId = "";
        
        if (null == openId) {
            /*
             * 根據得到的code參數,內部請求獲取openId的方法。
             */
            openId = getOpenId(request,response,code);
        }
        
        log.info("session中得到的openId值為:>>" + String.valueOf(openId));
        
        //根據openId查詢用戶信息
        Users user = myPageService.getUserByOpenId(String.valueOf(openId));

        ...
        return mv;
    }

    //發送請求,根據code獲取openId
    public String getOpenId(HttpServletRequest request, HttpServletResponse response,String code) {
        
        String content = "";
        String openId = "";
        String unionId = "";
        //封裝獲取openId的微信API
        StringBuffer url = new StringBuffer();
        url.append("https://api.weixin.qq.com/sns/oauth2/access_token?appid=")
        .append(Constants.APPID)
        .append("&secret=")
        .append(Constants.APPSECRET)
        .append("&code=")
        .append(code)
        .append("&grant_type=authorization_code");
        
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            content = HttpClient.requestGet(url.toString());
            Map map = objectMapper.readValue(content, Map.class);
            openId = String.valueOf(map.get("openid"));
            unionId = String.valueOf(map.get("unionid"));
            
            log.info("獲取的openID:" + openId);
            /*
             * 將openId保存到session中,當其他業務獲取openId時,
             * 可先從session中獲取openId.
             */
            request.getSession().setAttribute("openId", openId);
        } catch (JsonParseException e) {
            log.error("json解析失敗:", e);
        } catch (JsonMappingException e) {
            log.error("map轉換成json失敗:", e);
        } catch (Exception e) {
            log.error("http獲取openId請求失敗:", e);
        }
        return openId;
    }

可以看到getOpenId方法中,通過code值和appid,secret發送了一個http請求,用于獲取用戶的openId,請求成功返回如下格式內容:

{
   "access_token":"ACCESS_TOKEN",
   "expires_in":7200,
   "refresh_token":"REFRESH_TOKEN",
   "openid":"OPENID",
   "scope":"SCOPE"
}
##參數說明
access_token    網頁授權接口調用憑證,注意:此access_token與基礎支持的access_token不同
expires_in      access_token接口調用憑證超時時間,單位(秒)
refresh_token   用戶刷新access_token
openid          用戶唯一標識,請注意,在未關注公眾號時,用戶訪問公眾號的網頁,也會產生一個用戶和公眾號唯一的OpenID
scope           用戶授權的作用域,使用逗號(,)分隔

因為同一個微信用戶對每一個微信公眾號來說,都有唯一的標識就是這個openId。所以,我們拿到openId就能針對這個指定用戶來做一些其他的業務操作,靜默授權snsapi_base就到此結束了,并不會獲取得到微信的用戶信息。

snsapi_userinfo

若是不僅僅想要獲取微信用戶的openId,還想獲取未關注公眾號的微信用戶信息,那么可以通過snsapi_userinfo授權來實現。
(1) 重定向獲取code

Scope為snsapi_userinfo
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60
&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code
&scope=snsapi_userinfo&state=STATE#wechat_redirect

當微信用戶點擊這個頁面,會跳出授權頁面,如下圖:


image

(2) 得到openId
與靜默授權一樣,重定向到我們開發的三方頁面,則可以先獲取code值,在根據code值發送下面的連接請求,得到openId:

//通過request.getParameter("code")獲取code
獲取code后,請求以下鏈接獲取access_token: 
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

可以參考靜默授權java代碼實現詳情,此處省略。

(3) 獲取個人信息
在拿到微信用戶對應的openId之后,因為之前用戶已經同意授權后,就能通過以下請求連接獲取未關注的用戶個人信息:

http:GET(請使用https協議)
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

此處要注意的是access_token值,這個access_token的值是上面(2)方法調用返回的token,并不是JSSDK網頁調用基礎支持全局的token。響應返回json格式的用戶個人信息。

用戶管理-獲取用戶基本信息

微信公眾號開發文檔中,有指定的api 接口可以讓我們調用,獲取微信用戶的基本信息。這個接口調用的成功的前提條件是:所要獲取的微信用戶信息是已經關注了我們的微信公眾號的。若是該微信用戶沒有關注,則不能通過此接口調用,只能通過上述的網頁授權方式獲取用戶信息。詳情參考:用戶管理-獲取用戶基本信息

(1) 獲取用戶基本信息api
文檔中聲明的調用接口如下:

http請求方式: GET
https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

## 參數說明
access_token    是   調用接口憑證
openid  是   普通用戶的標識,對當前公眾號唯一
lang    否   返回國家地區語言版本,zh_CN 簡體,zh_TW 繁體,en 英語

這里要注意的是這個access_token是微信接口調用的憑證。與網頁授權通過code拿到的access_token是不同的。這個接口憑證,是全局token,也就是說,若是項目中要調用所有微信其他jssdk等接口,請求url參數中多數時候都是需要這個參數token值的。具體的可以查看下面的第(2)步獲取全局token。再次,就設定已經拿到了全局接口調用的access_token,并將該token保存到內存中。看看java中如何調用接口獲取微信用戶信息。

    public Users getWechatUserInfo(String openId) {
        //獲取保存在內存中的全局接口調用access_token
        String accessToken = Constants.ACCESS_TOKEN;
        log.info("全局token>>" + accessToken);

        //構造獲取用戶基本信息api
        StringBuffer url = new StringBuffer();
        url.append("https://api.weixin.qq.com/cgi-bin/user/info?")
           .append("access_token=").append(accessToken)
           .append("&openid=").append(openId).append("&lang=zh_CN");
        
        String content = "";
        ObjectMapper objectMapper = new ObjectMapper();
        Users user = null;
        try {
            for (int i = 1; i <= 3; i++) {
                //content就是json格式的用戶信息
                content = httpUtil.executeGet(url.toString());
                log.info("獲取微信用戶請求響應信息:>>" + content);
                Map map = objectMapper.readValue(content, Map.class);
                Object mopenId = map.get("openid");
                Object nickName = map.get("nickname");
                log.info("第" + i + "次獲取openId=" + openId + "的微信用戶昵稱:>>"+ nickName);
                if (openId.equals(mopenId) && nickName != null) {
                    /*
                     * 獲取微信用戶基本信息成功,并將信息封裝到平臺用戶對象中。
                     */
//                  user = myPageDao.getUserByOpenId(openId);
                    user = new Users();
                    if(user != null) {
                        user.setNickname(String.valueOf(nickName));
//                      user.setName(String.valueOf(nickName));
                        user.setSex((Integer) map.get("sex"));
                        user.setPictureURL(String.valueOf(map.get("headimgurl")));
                        user.setOpenid(String.valueOf(mopenId));
                        user.setUnionID(String.valueOf(map.get("unionid")));
                    }
                    log.info("調用微信得到的用戶信息:>>" + user.getNickname() + ",photo>>"+ user.getPictureURL());
                    return user;
                }
                log.info("第" + i + "次獲取openId=" + openId + "的微信用戶信息失敗!!");
            }

        } catch (JsonParseException e) {
            log.error("獲取微信基本用戶信息時,json轉換失敗:>>", e);
            e.printStackTrace();
        } catch (Exception e) {
            log.error("http請求執行錯誤:>>", e);
            e.printStackTrace();
        }
        return user == null ? new Users() : user;
    }

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

我們可以通過定時器定時調用獲取token的api請求,得到這個access_token就保存在內存中,若是其他接口需要使用,直接調用即可。這里官方也有說明:如果第三方不使用中控服務器,而是選擇各個業務邏輯點各自去刷新access_token,那么就可能會產生沖突,導致服務不穩定。,也就是不建議我們頻繁的手動調用這個api來更新access_token。

http請求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

## 參數說明
grant_type  是   獲取access_token填寫client_credential
appid   是   第三方用戶唯一憑證
secret  是   第三方用戶唯一憑證密鑰,即appsecret

## 返回
{"access_token":"ACCESS_TOKEN","expires_in":7200}

來看看java中如何獲取這個全局接口調用token:

    private void getAccessToken() {
        StringBuffer url = new StringBuffer();
        url.append("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential")
           .append("&appid=").append(Constants.APPID)
           .append("&secret=").append(Constants.APPSECRET);
        log.info("獲取全局accesss_token的請求:>>" + url.toString());
        try {
            String content;
            ObjectMapper objectMapper = new ObjectMapper();
            /*
             * 發送請求獲取access_token,最多發送3次請求進行獲取。
             */
            for(int i = 1; i <= 3; i++) {
                if(httpUtil == null) {
                    httpUtil = new HttpUtil();
                }
                content = httpUtil.executeGet(url.toString());
                try {
                    Map map = objectMapper.readValue(content, Map.class);
                    Object at = map.get("access_token");
                    log.info("第" + i + "次定時器獲取全局access_token:>>" + at);
                    if(null != at) {
                        //刷新內存中的全局ACCESS_TOKEN值。
                        Constants.ACCESS_TOKEN = String.valueOf(at);
                        log.info("全局access_token刷新成功!!");
                        break;
                    }
                    log.info("全局access_token刷新失敗!!");
                } catch (Exception e) {
                    log.error("獲取全局access_token時,json轉換失敗:" + e.getMessage());
                    break;
                }
            }
    
        } catch (Exception e) {
            log.error("獲取全局access_token失敗:" + e.getMessage());
        }
        
    }

在來多說幾句,這個如何用定時器來統一刷新內存中全局token,主要結合quartz定時器來實現。
第一步,要先引入定時器quartz依賴庫:

        <!-- 定時器 -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>1.8.6</version>
        </dependency>

第二步,實現定時器調用的job具體實現類:

@Service("accessTokenService")
public class AccessTokenService {

    //定時器調用方法
    public void execute() {
        getAccessToken();//上述代碼已經列出
    }

    /**
     * refresh: 提供一個入口,進行強制手動刷新token。
     */
    public static void refresh() {
        new AccessTokenService().getAccessToken();
    }

}

第三步,在spring配置文件中配置定時器:

## applicationContext.xml
    <!-- 應用程序定時器配置 -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="accessTokenTrigger" />
            </list>
        </property>
        <property name="autoStartup" value="true" />
    </bean>

    <!-- 配置定時器:每2小時刷新一次微信接口調用全局token -->
    <bean id="accessTokenTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="tokenJobDetail" />
        <property name="cronExpression" value="0 0 */2 * * ?" /><!-- 每隔2個小時觸發一次 -->
    </bean>
    <bean id="tokenJobDetail"
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="accessTokenService" />
        <property name="targetMethod" value="execute" />
        <property name="concurrent" value="false" />
        <!-- 是否允許任務并發執行。當值為false時,表示必須等到前一個線程處理完畢后才再啟一個新的線程 -->
    </bean>

第四步,要使這個定時器在服務器啟動時候,必須調用一次。基于服務器啟動時間,每間隔2個小時就進行token刷新:
需要我們在web.xml配置文件中配置監聽器listener,定義一個在服務器啟動時候,就進行調用的類方法。

## web.xml
<listener>
    <listener-class>com.cybbj.utils.AccessTokenInit</listener-class>
</listener>


## AccessTokenInit.java 集成ServletContextListener實現服務器啟動監聽
public class AccessTokenInit implements ServletContextListener{

    public void contextInitialized(ServletContextEvent sce) {
            AccessTokenService.refresh();
    }

    public void contextDestroyed(ServletContextEvent sce) {
        
    }

}

總結

至此,這個微信公眾號的基本基礎開發配置完成了,后面還有JSSDK頁面開發要進行說明。在微信開發過程中,只要嚴格按照微信官方的開發文檔進行操作就應該沒有什么大的問題,感覺都是調用接口api,沒啥難度....

不過,還是有很長的路要走啊....

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容