大概流程:
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,用于微信授权