微信公众号用java中控服务器-实现用户网页授权和获取使用JS-SDK权限

一、网页授权,是指用户点击微信公众号里的自定义菜单在打开页面中获取授权用户信息,可以用来实现免登录。
下图是需要引导用户点开的地址其中redirect_uri=指向你真正要跳转的地址,比如可以在自定义菜单跳转地址中改成这种地址形式,就可以在页面中获取到地址栏的code。
这里写图片描述

/**
     * 获取微信用户信息或者用户openid
     * @param code 微信给菜单地址重定向后带地址栏的参数
     * @param type 1只返回openid,20返回用户信息
     * @return
     * @throws IOException
     */
    @RequestMapping(value="/getWxUser", method=RequestMethod.POST)
    @ResponseBody
    public Object getWxUser(String code, Integer type) throws IOException{
        log.debug(code);
        log.debug(type);
        if(Assert.isInvalidString(code) || type==null){
            return null;
        }
        //获取access_token和openid
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("appid", SysConfig.getValue(SysConstants.Config.WX_APPID));//微信公众号的Appid
        params.put("secret", SysConfig.getValue(SysConstants.Config.WX_SECRET));//微信公众号的AppSecret
        params.put("code", code);//微信给菜单地址重定向后带地址栏的参数
        params.put("grant_type", "authorization_code");
        HttpURLConnection conn = HttpUtil.doGet(SysConstants.Url.WX_OAUTH_ACCESS_TOKEN_URL, params, null);
        JSONObject result = JSONObject.parseObject(HttpUtil.getString(conn));
        log.debug(result);
        if(type==1){
            return result;
        }else if(type==20){
            //获取用户信息
            params = new HashMap<String, Object>();
            //这个access_token是网页授权专用的,和jssdk中的2小时时效,一天最多2000次的那个不一样,这个没有限制次数
            params.put("access_token", result.get("access_token"));
            params.put("openid", result.get("openid"));
            params.put("lang", "zh_CN");
            conn = HttpUtil.doGet(SysConstants.Url.WX_USERINFO_URL, params, null);
            result = JSONObject.parseObject(HttpUtil.getString(conn));
            log.debug(result);
            return result;
        }else{
            return null;
        }
    }

二、获取微信JS-SDK权限
获取微信js-sdk权限可以通过微信来调用手机的一些功能,比如拍照。
这里要用到数据库保存access_token和jsapi_ticket,因为这两个都只有2小时时效,一天最多2000次的。

/**
     * 获取wx.config的配置参数
     * @param url
     * @return
     * @throws Exception 
     */
    @RequestMapping(value="/getWxJS", method=RequestMethod.POST)
    @ResponseBody
    public Object configWxJS(String url) throws Exception{
        JSONObject json = new JSONObject();
        String appId = SysConfig.getValue(SysConstants.Config.WX_APPID);

        //1、数据库中查找jsapi_ticket,用修改时间与现在的时间比较是否过期(7200秒)。
        //2、如果jsapi_ticket过期(超过7200秒),数据库中查找access_token,用修改时间与现在的时间比较是否过期(7200秒),如果jsapi_ticket没有过期直接用来加密签名
        //3、如果access_token过期,先重新获取access_token,如果没有过期使用access_token获取jsapi_ticket
        List<Config> configs = configService.findByProperty("configKey", "jsapi_ticket");//数据库中查找jsapi_ticket
        Config jsapiticket = Assert.isValidCollection(configs)?configs.get(0):null;
        Long timestamp = System.currentTimeMillis();//当前时间
        if(jsapiticket==null || Assert.isInvalidString(jsapiticket.getConfigValue()) || (timestamp-jsapiticket.getModifyTime().getTime())/1000l>=jsapiticket.getExpiresIn()){//判断jsapi_ticket是否过期
            //需要修改jsapi_ticket
            configs = configService.findByProperty("configKey", "access_token");//数据库查找access_token
            Config accesstoken = Assert.isValidCollection(configs)?configs.get(0):null;
            if(accesstoken==null || Assert.isInvalidString(accesstoken.getConfigValue()) || (timestamp-accesstoken.getModifyTime().getTime())/1000l>=accesstoken.getExpiresIn()){//判断access_token是否过期
                //需要修改access_token
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("grant_type", "client_credential");
                params.put("appid", appId);
                params.put("secret", SysConfig.getValue(SysConstants.Config.WX_SECRET));
                HttpURLConnection conn = HttpUtil.doGet(SysConstants.Url.WX_JS_ACCESS_TOKEN_URL, params, null);
                JSONObject result = JSONObject.parseObject(HttpUtil.getString(conn));
                log.debug(result.toString());
                if(Assert.isValidString(result.getString("access_token"))){
                    accesstoken = accesstoken==null?new Config():accesstoken;
                    accesstoken.setConfigKey("access_token");
                    accesstoken.setConfigValue(result.getString("access_token"));
                    accesstoken.setExpiresIn(result.getLong("expires_in"));
                    accesstoken.setModifyTime(new Date(timestamp));
                    configService.saveOrUpdate(accesstoken);
                }else{
                     throw new Exception("获取access_token出错。");
                }
            }
            //使用access_token获取修改jsapi_ticket
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("access_token", accesstoken.getConfigValue());
            params.put("type", "jsapi");
            HttpURLConnection conn = HttpUtil.doGet(SysConstants.Url.WX_JSAPI_TICKET, params, null);
            JSONObject result = JSONObject.parseObject(HttpUtil.getString(conn));
            log.debug(result.toString());
            if(Assert.isValidString(result.getString("ticket"))){
                jsapiticket = jsapiticket==null?new Config():jsapiticket;
                jsapiticket.setConfigKey("jsapi_ticket");
                jsapiticket.setConfigValue(result.getString("ticket"));
                jsapiticket.setExpiresIn(result.getLong("expires_in"));
                jsapiticket.setModifyTime(new Date(timestamp));
                configService.saveOrUpdate(jsapiticket);
            }else{
                throw new Exception("获取jspapi_ticket出错。");
            }
        }
        //使用jsapi_ticket加密签名
        String nonceStr = UUID.randomUUID().toString().replaceAll("-", "").substring(10, 26);
        String str = "jsapi_ticket="+jsapiticket.getConfigValue()+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url="+url;
        String signature = DigestUtils.shaHex(str);

        json.put("appId", appId);
        json.put("signature", signature);
        json.put("nonceStr", nonceStr);
        json.put("timestamp", String.valueOf(timestamp));
        log.debug(json.toString());
        return json;
    }

通过这个接口就可以获取到页面中调用微信的js所需要的配置信息
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: ”, // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: ”, // 必填,生成签名的随机串
signature: ”,// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

三、一些重要的常量

public class SysConstants {
    private SysConstants(){}

    public class Url{
        /**
         * 获取授权access_token的地址
         * 参数 :?appid=${APPID}&secret=${SECRET}&code=${CODE}&grant_type=authorization_code
         */
        public static final String WX_OAUTH_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
        /**
         * 获取用户信息的地址
         * 参数 :?access_token=${ACCESS_TOKEN}&openid=${OPENID}&lang=zh_CN
         */
        public static final String WX_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";
        /**
         * 获取基础接口的access_token地址
         * 参数 :?grant_type=client_credential&appid=APPID&secret=APPSECRET
         */
        public static final String WX_JS_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
        /**
         * 获取jsapiticket地址
         * ?access_token=ACCESS_TOKEN&type=jsapi
         */
        public static final String WX_JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    }
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值