• SpringCloud : 接入 微信公众号平台(二)、菜单跳转auth2.0授权


    大概流程:

    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:

    公众号开发文档wiki

    Java开发微信公众号之整合weixin-java-tools框架开发微信公众号

    从零实现 Spring Boot 2.0 整合 weixin-java-mp(weixin-java-tools) 获取 openId,用于微信授权

    Demo 列表

    1. 微信支付 Demo:GitHub码云
    2. 企业号/企业微信 Demo:GitHub码云
    3. 微信小程序 Demo:GitHub码云
    4. 开放平台 Demo:GitHub码云
    5. 公众号 Demo:
      • 使用 Spring MVC 实现的公众号 Demo:GitHub码云
      • 使用 Spring Boot 实现的公众号 Demo(支持多公众号):GitHub码云
      • 含公众号和部分微信支付代码的 Demo:GitHub码云
  • 相关阅读:
    Postgresql pg_dump 与 pg_restore 使用举例
    Postgresql pg_restore
    Postgresql pg_dump
    PostgreSQL 常用数据视图/字典
    PostgreSQL 数据目录结构
    Linux gdb分析core dump文件
    PostgreSQL 配置参数
    PostgreSQL 不要使用kill -9 杀 Postgresq 用户进程
    Postgresql 日志相关
    PostgreSQL 学习手册-模式Schema
  • 原文地址:https://www.cnblogs.com/phpdragon/p/12557686.html
Copyright © 2020-2023  润新知