大概流程:
1. 通過 https://域名/auth/getOauthUrl 獲取到auth2.0的授權跳轉地址(也就是微信公眾號跳轉菜單綁定的鏈接)。
如何添加菜單請參考代碼:WxMenuController.java。
核心代碼就是 wxMpService.oauth2buildAuthorizationUrl("處理授權回調的url", WxConsts.OAuth2Scope.SNSAPI_USERINFO, this.urlEncode("目標鏈接"));
2. 然后訪問該鏈接,微信為彈出一個確認授權彈窗,用戶確認通過之后,會跳轉到 https://域名/auth/callback 處理微信授權回調。
3. 然后callback 方法處理完畢后,再重定向到你需要重定向的目標鏈接。
import com.phpdragon.wechat.proxy.config.WeChatConfig; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.view.RedirectView; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.*; /** * 處理微信auth2.0授權 */ @Slf4j @RequestMapping("/auth/") @RestController public class AuthController { @Autowired private WeChatConfig weChatConfig; /** * 返回授權地址,用於微信中用戶再次確認授權 * 參考:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#0 * * @param appId * @param redirectUrl * @return */ @ResponseBody @GetMapping("/getOauthUrl") public String getOauthUrl(@RequestParam("app_id") String appId, @RequestParam("redirect_url") String redirectUrl) { String localAuthHandleUrl = this.getLocalAuthHandleUrl(appId); WxMpService wxMpService = weChatConfig.getWxMpService(appId); String oauthUrl = wxMpService.oauth2buildAuthorizationUrl(localAuthHandleUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO, this.urlEncode(redirectUrl)); log.info("【微信網頁授權】獲取code,oauthUrl={}", oauthUrl); return oauthUrl; } /** * 構造授權地址,並直接重定向,用於微信中用戶再次確認授權 * 參考:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#0 * * @param appId * @param redirectUrl * @return */ @GetMapping("/redirectOauthUrl") public RedirectView redirectAuthorizeUrl(@RequestParam("app_id") String appId, @RequestParam("redirect_url") String redirectUrl) { String localAuthHandleUrl = this.getLocalAuthHandleUrl(appId); WxMpService wxMpService = weChatConfig.getWxMpService(appId); String oauthUrl = wxMpService.oauth2buildAuthorizationUrl(localAuthHandleUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO, this.urlEncode(redirectUrl)); log.info("【微信網頁授權】獲取code,oauthUrl={}", oauthUrl); return new RedirectView(oauthUrl); } /** * 處理微信授權回調 * 參考:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#0 * * @param code * @param returnUrl * @return * @throws Exception */ @GetMapping("/callback/{app_id}") public RedirectView callback(@PathVariable("app_id") String appId, @RequestParam("code") String code, @RequestParam("state") String returnUrl) throws Exception { log.info("【微信網頁授權】code={}", code); log.info("【微信網頁授權】state={}", returnUrl); WxMpService wxMpService = weChatConfig.getWxMpService(appId); WxMpOAuth2AccessToken wxMpOauth2AccessToken; try { //獲取access_token wxMpOauth2AccessToken = wxMpService.oauth2getAccessToken(code); } catch (WxErrorException e) { log.info("微信網頁授權,error:{},{}", e.getMessage(), e); throw new Exception(e.getError().getErrorMsg()); } String openId = wxMpOauth2AccessToken.getOpenId(); log.info("【微信網頁授權】openId={}", openId); //這里的access-token是個人的,不是全局那個access-token,不能全局共享 //獲得用戶基本信息 //WxMpUser mpUser = wxMpService.oauth2getUserInfo(wxMpOauth2AccessToken, null); //log.info("【微信網頁授權】用戶信息={}", JSONObject.toJSONString(mpUser)); //如果有配置動態獲取授權跳轉地址,則使用,否則使用菜單中默認配置好的跳轉地址 String redirectUrl = this.getOauthRedirectUrl(appId, openId); if (StringUtils.isBlank(redirectUrl)) { Map<String, String> params = new HashMap<>(2); params.put("openid", openId); params.put("app_id", appId); redirectUrl = this.appendParam(returnUrl, params); } return new RedirectView(redirectUrl); } /** * 獲取授權通過后重定向后的地址 * * @param appId * @param openId * @return */ @Nullable private String getOauthRedirectUrl(String appId, String openId) { //TODO: 實現調轉地址的db化 return "http://www.baidu.com"; } /** * 獲取本地授權地址 * * @return */ private String getLocalAuthHandleUrl(String appId) { return WeChatConfig.CURRENT_HOST + "/auth/callback/" + appId; } private String urlEncode(String str) { try { return URLEncoder.encode(str, "utf8"); } catch (Exception var3) { return str; } } private String appendParam(String originUrl, Map<String, String> appendParams) { URL url = newUrl(originUrl); if (Objects.isNull(url)) { return ""; } else { StringBuilder sb = new StringBuilder(url.getProtocol()); sb.append("://"); sb.append(url.getHost()); if (url.getPort() > -1) { sb.append(":"); sb.append(url.getPort()); } sb.append(url.getPath()); sb.append("?"); if (StringUtils.isNoneBlank(new CharSequence[]{url.getQuery()})) { String[] queryArr = StringUtils.split(url.getQuery(), "&"); Map<String, String> params = new LinkedHashMap(queryArr.length); String[] var6 = queryArr; int var7 = queryArr.length; for (int var8 = 0; var8 < var7; ++var8) { String item = var6[var8]; if (StringUtils.isNoneBlank(new CharSequence[]{item})) { String[] itemArr = StringUtils.split(item, "="); params.put(itemArr[0], itemArr[1]); } } params.putAll(appendParams); sb.append(this.buildQuery(params)); } else { sb.append(this.buildQuery(appendParams)); } if (StringUtils.isNoneBlank(new CharSequence[]{url.getRef()})) { sb.append("#"); sb.append(url.getRef()); } return sb.toString(); } } private String buildQuery(Map<String, String> params) { StringBuilder sb = new StringBuilder(); int total = params.size(); Iterator var3 = params.entrySet().iterator(); while (var3.hasNext()) { Map.Entry<String, String> entry = (Map.Entry) var3.next(); --total; sb.append((String) entry.getKey()); sb.append("="); sb.append((String) entry.getValue()); if (total > 0) { sb.append("&"); } } return sb.toString(); } private URL newUrl(String url) { try { return new URL(url); } catch (MalformedURLException var2) { log.error("實例化URI失敗,error:{},{}", var2.getMessage(), var2); return null; } } }
PS:
Java開發微信公眾號之整合weixin-java-tools框架開發微信公眾號
從零實現 Spring Boot 2.0 整合 weixin-java-mp(weixin-java-tools) 獲取 openId,用於微信授權
Demo 列表