Java微信公眾號開發之使用攔截器獲取粉絲openID

自由不過一種漂泊發表於2019-04-08

目的

        本次實現的目的是:在微信公眾號專案中,可能在每次訪問頁面的時候需要帶上openID或者授權,查資料庫太耗效能、多次多個地方去調授權介面也不是最佳的方案,如果能利用攔截器攔截到每次請求訪問後臺,這個時候在攔截器裡判斷是否已經有這個粉絲的openID,如果獲取到了openid,就不用去走授權獲取使用者資訊介面了,那麼從哪裡取這個openID呢,可以從Redis或其他快取庫裡取,我使用了最簡單:從Session裡去取openID,取的前提是在第一次授權獲取使用者資訊後,你需要將openId存到session裡去,然每次請求攔截器會攔截請求從session獲取openID,來做業務判斷,如果取不到就去授權;

 

一、實現

  1.建立一個攔截器,攔截器配置如下,對攔截器不熟悉的請看:如何自定義一個攔截器

    在spring-mvc.xml檔案中新增一個攔截器  (注:如果是SpringBoot專案,請按照SpringBoot建立攔截器方式建立攔截器)

	<!-- 攔截器配置,攔截順序:先執行後定義的,排在第一位的最後執行。-->
	<mvc:interceptors>	
		<!-- 微信授權攔截器   -->
		<mvc:interceptor>
			<mvc:mapping path="/mobile/**" />
			<bean class="com.thinkgem.jeesite.modules.sys.interceptor.WXOAuthInterceptor" />
		</mvc:interceptor>		
	</mvc:interceptors>

  2.新建一個攔截器類WXOAuthInterceptor

  WXOAuthInterceptor.java 

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.thinkgem.jeesite.common.service.BaseService;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.modules.wechat.service.WXOAuthService;

/**
 * 微信
 * 
 * <pre>
 *   
 * &#64;author cao_wencao  
 * &#64;date 2018年8月13日
 * </pre>
 */
@Slf4j
public class WXOAuthInterceptor extends BaseService implements HandlerInterceptor {

	@Autowired
	private WXOAuthService wXOAuthService;

	@Override
	@Transactional(readOnly = false)
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {		
		// 獲取 seesion openid
	    log.warn("==============執行順序: 1、preHandle================");
	    String openid = (String) request.getSession().getAttribute("openid");
        if (StringUtils.isNotBlank(openid)){
            return true;
        }
        String code = request.getParameter("code"); // 獲取引數中 的 code 引數
        if (StringUtils.isNotBlank(code)) {
            wXOAuthService.userInfo(request, response);
        } else {
            wXOAuthService.oauth(request, response);
        }
         return true;
	}

	@Override
	@Transactional(readOnly = false)
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	    log.warn("==============執行順序: 2、postHandle================");
//		request.getSession().setAttribute("openid", "oJIGa0RLwXB8r5vxYphyKCOQGxz1"); // 設定 Session Openid

//		// 獲取 seesion openid
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	    log.warn("==============執行順序: 3、afterCompletion================");

	}

}

   

3.授權介面服務類WXOauthService

 注:WXOauthService中userInfo方法為請求授權介面,在請求授權獲取使用者資訊後需要將openid存進session裡去,這樣在攔截器中才可以取到粉絲的openid

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.modules.app.entity.user.Follow;
import com.thinkgem.jeesite.modules.app.service.user.FollowService;
import com.thinkgem.jeesite.modules.app.service.user.MemberService;
import com.thinkgem.jeesite.modules.wechat.receiveVo.FansVo;

/**
 * 網頁授權 服務
 * @author caowencao
 *
 */
@Service
@Transactional(readOnly = true)
public class WXOAuthService {
	private static final Logger logger = LoggerFactory.getLogger(WXOAuthService.class);
	@Autowired
    private WxMpService wxMpService;
	@Autowired
	private FollowService followService;
	@Autowired
	private MemberService memberService;
	/**
	 * 網頁授權
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	public void oauth(HttpServletRequest request, HttpServletResponse response) throws Exception{
		String backUrl = request.getRequestURL().toString();  //取得當前 URL
        String redirectUri = wxMpService.oauth2buildAuthorizationUrl(backUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO,"1");
        logger.info("redirectUri地址={}", redirectUri);// 日誌
        response.sendRedirect(redirectUri);
	}
	
	/**
	 * 獲取使用者資訊
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	@Transactional(readOnly = false)
	public void userInfo(HttpServletRequest request, HttpServletResponse response) throws Exception{
		String code = request.getParameter("code");
		if(StringUtils.isBlank(code))
			oauth(request, response);   //繼續授權
        // 通過code換取access token
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
        String openId = null;
        try {
            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
            openId = wxMpOAuth2AccessToken.getOpenId();
            logger.info("openId={}", openId);
            String lang = "zh_CN";
            WxMpUser wxMpUser = this.wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, lang);
            // TODO 操作儲存使用者資訊到資料庫
            // 儲存通過授權拿到的使用者資訊
            followService.saveOauthFollowInfo(wxMpUser);
//            Follow follow = followService.findFollowByOpenId(openId);
//            if (null == follow && null != wxMpUser) {
//                // 儲存通過授權拿到的使用者資訊
//                followService.saveOauthFollowInfo(wxMpUser);
//            }
            logger.info("網頁授權獲取使用者資訊 :" + wxMpUser.toString());
            FansVo fans = new FansVo();
            // 獲取粉絲賬號
            String account =  memberService.getAccountByOpenid(openId);
            if (!StringUtils.isBlank(account)) {
                fans.setAccount(account);
                fans.setOpenid(openId);
            }           
            request.getSession().setAttribute("fans", fans); //  session中設定粉絲賬號和openid
            
            request.getSession().setAttribute("openid", openId); //設定 Session Openid
        }
        catch (WxErrorException e) {
            logger.error("【微信網頁授權】{}", e.getMessage());
            oauth(request, response);
            throw new RuntimeException("網頁授權失敗!");
        }
	}
	
}

   好了,到這裡使用攔截器獲取微信openID、授權獲取使用者資訊就實現了,像這樣封裝複用性比較高;

相關文章