前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java微信公众平台开发_05_微信网页授权

Java微信公众平台开发_05_微信网页授权

作者头像
shirayner
发布于 2018-08-10 02:47:52
发布于 2018-08-10 02:47:52
6.3K00
代码可运行
举报
文章被收录于专栏:Java成神之路Java成神之路
运行总次数:0
代码可运行

GitHub源码:https://github.com/shirayner/weixin_gz

一、本节要点

1.网页授权回调域名

登录微信公众平台后台, 开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息 - 修改,

这里填写的是域名(是一个字符串),而不是URL

2. 获取code

获取code的流程

(1)创建一个跳转按钮,链接为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxa0064ea657f80062&redirect_uri=http%3A%2F%2Frayner.nat300.top%2Fweixin_gz%2FIDAuthentication.jsp&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

(2)在jsp页面 IDAuthentication.jsp 上接收code

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
         //1.接收code和state
         String code= request.getParameter("code");
         String state=request.getParameter("state");

 3.通过code换取网页授权access_token

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 //3.通过code换取网页授权access_token
    private static final String GET_ACCESSTOKEN_BYCODE_URL="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; 


/**
     * @desc : 3.通过code换取网页授权access_token
     *  
     * @param appId  第三方用户唯一凭证
     * @param appSecret  第三方用户唯一凭证密钥,即appsecret
     * @param Code  code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
     * 
     * @return
     * access_token    网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
     * expires_in    access_token接口调用凭证超时时间,单位(秒)
     * refresh_token    用户刷新access_token
     * openid    用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
     * scope    用户授权的作用域,使用逗号(,)分隔
     * 
     * @throws Exception String
     */
    public static JSONObject getAccessTokenByCode(String appId,String appSecret,String code) throws Exception {
        //1.获取请求url
        String url=GET_ACCESSTOKEN_BYCODE_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取accessToken
        JSONObject returnJsonObject=null;
        if (null != jsonObject) {  
            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取accessToken
            }else {
                returnJsonObject=jsonObject;
            }  
        }  


        return returnJsonObject;
    }

4.通过网页授权access_token 拉取用户信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时                                  
    private static final String GET_SNS_USERINFO_URL="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";


/**
     * @desc :3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时      
     *  
     * @param accessToken  网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
     * @param openId 用户的唯一标识
     * 
     * @return
     * openid    用户的唯一标识
     * nickname    用户昵称
     * sex    用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
     * province    用户个人资料填写的省份
     * city    普通用户个人资料填写的城市
     * country    国家,如中国为CN
     * headimgurl    用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
     * privilege    用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
     * unionid    只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
     * 
     * @throws Exception JSONObject
     */
    public static JSONObject getSNSUserInfo(String accessToken,String openId ) throws Exception {
        //1.获取请求url
        String url=GET_SNS_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取菜单数据
        JSONObject returnJsonObject=null;
        if (null != jsonObject) {  

            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取菜单数据
            } else {
                returnJsonObject= jsonObject;
            } 
        }   

        return returnJsonObject;


    }

二、代码实现

1.Token工具类—AuthHelper

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.ray.weixin.gz.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Formatter;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.ray.weixin.gz.config.Env;
import com.ray.weixin.gz.service.invoice.InvoiceService;


/**
 * 微信公众号 Token、配置工具类
 * @desc  : AccessToken、Jsticket 、Jsapi
 * 
 * @author: shirayner
 * @date  : 2017年9月27日 下午5:00:25
 */
public class AuthHelper {
    private static final Logger logger = LogManager.getLogger(AuthHelper.class);

    //1.获取access_token的接口地址,有效期为7200秒
    private static final String GET_ACCESSTOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; 
    //2.获取getJsapiTicket的接口地址,有效期为7200秒 
    private static final String GET_JSAPITICKET_URL="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; 

    //3.通过code换取网页授权access_token
    private static final String GET_ACCESSTOKEN_BYCODE_URL="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; 


    /**
     * @desc :1.获取access_token 
     *  
     * @param appId  第三方用户唯一凭证
     * @param appSecret  第三方用户唯一凭证密钥,即appsecret
     * 
     * @return
     *      access_token    获取到的凭证
     *      expires_in    凭证有效时间,单位:秒
     * @throws Exception String
     */
    public static String getAccessToken(String appId,String appSecret) throws Exception {
        //1.获取请求url
        String url=GET_ACCESSTOKEN_URL.replace("APPID", appId).replace("APPSECRET", appSecret);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取accessToken
        String accessToken="";  
        if (null != jsonObject) {  
            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取accessToken
            }else {
                accessToken=jsonObject.getString("access_token");
            }  
        }  


        return accessToken;
    }


    /**
     * @desc :2.获取JsapiTicket
     *  
     * @param accessToken  有效凭证
     * @return
     * @throws Exception String
     */
    public static String getJsapiTicket(String accessToken) throws Exception {
        //1.获取请求url
        String url=GET_JSAPITICKET_URL.replace("ACCESS_TOKEN", accessToken);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取accessToken
        String jsapiTicket="";  
        if (null != jsonObject) {  
            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取jsapiTicket
            }else {
                jsapiTicket=jsonObject.getString("ticket");
            }  
        }  


        return jsapiTicket;
    }

    /**
     * @desc : 3.通过code换取网页授权access_token
     *  
     * @param appId  第三方用户唯一凭证
     * @param appSecret  第三方用户唯一凭证密钥,即appsecret
     * @param Code  code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
     * 
     * @return
     * access_token    网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
     * expires_in    access_token接口调用凭证超时时间,单位(秒)
     * refresh_token    用户刷新access_token
     * openid    用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
     * scope    用户授权的作用域,使用逗号(,)分隔
     * 
     * @throws Exception String
     */
    public static JSONObject getAccessTokenByCode(String appId,String appSecret,String code) throws Exception {
        //1.获取请求url
        String url=GET_ACCESSTOKEN_BYCODE_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取accessToken
        JSONObject returnJsonObject=null;
        if (null != jsonObject) {  
            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取accessToken
            }else {
                returnJsonObject=jsonObject;
            }  
        }  


        return returnJsonObject;
    }


    /**
     * @desc :4.获取前端jsapi需要的配置参数
     *  
     * @param request
     * @return String
     */
    public static String getJsapiConfig(HttpServletRequest request){  

        //1.准备好参与签名的字段
        //1.1 url
        /* 
         *以http://localhost/test.do?a=b&c=d为例 
         *request.getRequestURL的结果是http://localhost/test.do 
         *request.getQueryString的返回值是a=b&c=d 
         */  
        String urlString = request.getRequestURL().toString();
        String queryString = request.getQueryString();
        String queryStringEncode = null;
        String url;
        if (queryString != null) {
            queryStringEncode = URLDecoder.decode(queryString);
            url = urlString + "?" + queryStringEncode;
        } else {
            url = urlString;
        }

        //1.2 noncestr
        String nonceStr=UUID.randomUUID().toString();      //随机数
        //1.3 timestamp
        long timeStamp = System.currentTimeMillis() / 1000;     //时间戳参数  

        String signedUrl = url;

        String accessToken = null;
        String ticket = null;

        String signature = null;       //签名


        try {  
            //1.4 jsapi_ticket
            accessToken=getAccessToken(Env.APP_ID, Env.APP_SECRET);  
            ticket=getJsapiTicket(accessToken);  

            //2.进行签名,获取signature
            signature=getSign(ticket,nonceStr,timeStamp,signedUrl);  


        } catch (Exception e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  

        logger.info("accessToken:"+accessToken);
        logger.info("ticket:"+ticket);
        logger.info("nonceStr:"+nonceStr);
        logger.info("timeStamp:"+timeStamp);
        logger.info("signedUrl:"+signedUrl);
        logger.info("signature:"+signature);
        logger.info("appId:"+Env.APP_ID);




        String configValue = "{signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
                + timeStamp + "',appId:'" + Env.APP_ID + "'}";
        logger.info("configValue:"+configValue);

        return configValue;  
    }  


    /**
     * @desc : 4.1 生成签名的函数 
     *  
     * @param ticket jsticket
     * @param nonceStr 随机串,自己定义
     * @param timeStamp 生成签名用的时间戳 
     * @param url 需要进行免登鉴权的页面地址,也就是执行dd.config的页面地址 
     * @return
     * @throws Exception String
     */

    public static String getSign(String jsTicket, String nonceStr, Long timeStamp, String url) throws Exception {  
        String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "&timestamp=" + timeStamp + "&url=" + url;
        System.out.println(plainTex);
        try {  
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(plainTex.getBytes("UTF-8"));
            return byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception(e.getMessage());  
        } catch (UnsupportedEncodingException e) {  
            throw new Exception(e.getMessage());  
        }  
    }  

    /**
     * @desc :4.2 将bytes类型的数据转化为16进制类型  
     *  
     * @param hash
     * @return 
     *   String
     */
    private static String byteToHex(byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", new Object[] { Byte.valueOf(b) });
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }


    /** 5.获取前端所需发票签名参数
     * 
     * @desc :
     *(1)将 api_ticket、appid、timestamp、nonceStr、cardType的value值进行字符串的字典序排序。
     *(2)再将所有参数字符串拼接成一个字符串进行sha1加密,得到cardSign。
     * 
     * @return String
     *  timestamp :卡券签名时间戳
        nonceStr  : 卡券签名随机串
        signType  : 签名方式,默认'SHA1'
        cardSign  : 卡券签名
     *   
     */
    public static String getInvoiceConfig(){ 
        //1.准备好签名参数
        //1.1 api_ticket  授权页ticket
        String apiTicket=null;
        try {
            String  accessToken = AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
            apiTicket=InvoiceService.getAuthPageTicket(accessToken);
        } catch (Exception e) {
            logger.info("获取授权页ticket失败");
            e.printStackTrace();
        }


        //1.2 appid
        String appId=Env.APP_ID;

        //1.3 timestamp 时间戳
        String timeStamp = System.currentTimeMillis() / 1000 +"";     

        //1.4 nonceStr 随机数
        String nonceStr=UUID.randomUUID().toString();    

        //1.5 cardType
        String cardType="INVOICE";

        //2.获取签名
        String cardSign=null;
        try {

            cardSign = AuthHelper.getCardSign(apiTicket, appId, timeStamp, nonceStr, cardType);

        } catch (Exception e) {
            logger.info("获取发票签名失败");
            e.printStackTrace();
        }

        String signType="SHA1";

        logger.info("apiTicket:"+apiTicket);
        logger.info("appId:"+appId);
        logger.info("timeStamp:"+timeStamp);
        logger.info("nonceStr:"+nonceStr);
        logger.info("cardType:"+cardType);
        logger.info("cardSign:"+cardSign);
        logger.info("signType:"+signType);

        //3.返回前端所需发票签名参数
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("timestamp", timeStamp);
        jsonObject.put("nonceStr",nonceStr );
        jsonObject.put("signType",signType );
        jsonObject.put("cardSign", cardSign);

        String configValue = jsonObject.toJSONString();
        logger.info("configValue:"+configValue);

        return configValue;  
    }  



    /**
     * @desc :5.1获取发票签名
     *  
     * @param apiTicket  授权页ticket,见InvoiceService
     * @param appId  
     * @param timeStamp 时间戳
     * @param nonceStr  随机串
     * @param cardType 填入INVOICE
     * @return
     * @throws Exception 
     *   String
     */
    public static String getCardSign(String apiTicket, String appId, String timeStamp, String nonceStr,String cardType) throws Exception {  
        //1.将 api_ticket、appid、timestamp、nonceStr、cardType的value值进行字符串的字典序排序。
        //注意:是value值值
        String[] array = new String[] { apiTicket, appId, timeStamp, nonceStr,cardType};
        StringBuffer sb = new StringBuffer();
        // 字符串排序
        Arrays.sort(array);
        for (int i = 0; i < 5; i++) {
            sb.append(array[i]);
        }
        String plainTex = sb.toString();

        //String plainTex = apiTicket+appId+cardType+nonceStr+timeStamp;
        
        System.out.println("plainTex:"+plainTex);
        try {  
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(plainTex.getBytes("UTF-8"));
            return byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception(e.getMessage());  
        } catch (UnsupportedEncodingException e) {  
            throw new Exception(e.getMessage());  
        }  
    }  

    public static String getSHA1(String apiTicket, String appId, String timeStamp, String nonceStr,String cardType) throws Exception{
        System.out.println("getSHA1-----------");
        try {
            String[] array = new String[] { apiTicket, appId, timeStamp, nonceStr,cardType};
            StringBuffer sb = new StringBuffer();
            // 字符串排序
            Arrays.sort(array);
            for (int i = 0; i < 5; i++) {
                sb.append(array[i]);
            }
            String str = sb.toString();
            logger.info("str:"+str);
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();

            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("获取发票签名失败");
        }
    }


}

2.用户管理业务类—UserService

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.ray.weixin.gz.service.user;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.ray.weixin.gz.util.HttpHelper;

/**@desc  : 用户管理
 * 
 * @author: shirayner
 * @date  : 2017年10月31日 下午5:37:08
 */
public class UserService {
    private static final Logger logger = LogManager.getLogger(UserService.class);

    //1. 获取用户基本信息(UnionID机制)
    private static final String GET_USERINFO_URL="https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    //2.1 获取用户列表(从指定的next_openid的下一个开始获取)
    private static final String LIST_USER_URL="https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
    //2.2 获取所有用户列表
    private static final String LIST_ALLUSER_URL="https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN";
    //3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时                                  
    private static final String GET_SNS_USERINFO_URL="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";




    /**
     * @desc :1.获取用户基本信息(UnionID机制)
     *  
     * @param accessToken  有效凭证
     * @param openId 普通用户的标识,对当前公众号唯一
     * 
     * @return  用户详细信息
     * subscribe    用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
     * openid    用户的标识,对当前公众号唯一
     * nickname    用户的昵称
     * sex    用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
     * city    用户所在城市
     * country    用户所在国家
     * province    用户所在省份
     * language    用户的语言,简体中文为zh_CN
     * headimgurl    用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),
     *              用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
     * subscribe_time    用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
     * unionid    只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
     * remark    公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
     * groupid    用户所在的分组ID(兼容旧的用户分组接口)
     * tagid_list    用户被打上的标签ID列表
     * 
     * @throws Exception JSONObject
     */
    public static JSONObject getUserInfo(String accessToken,String openId ) throws Exception {
        //1.获取请求url
        String url=GET_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取菜单数据
        JSONObject returnJsonObject=null;
        if (null != jsonObject) {  

            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取菜单数据
            } else {
                returnJsonObject= jsonObject;
            } 
        }   

        return returnJsonObject;
    }

    /** 2.1  获取用户列表(从指定的next_openid的下一个开始获取)
     * 
     * @desc :一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
     *  
     * @param accessToken 调用接口凭证
     * @param nextOpenId  从指定的next_openid的下一个开始获取
     * 
     * @return
     * total    关注该公众账号的总用户数
     * count    拉取的OPENID个数,最大值为10000
     * data    列表数据,OPENID的列表
     * next_openid    拉取列表的最后一个用户的OPENID
     *   
     * @throws Exception JSONObject
     */
    public static JSONObject listUser(String accessToken,String nextOpenId ) throws Exception {
        //1.获取请求url
        String url=LIST_USER_URL.replace("ACCESS_TOKEN", accessToken).replace("NEXT_OPENID", nextOpenId);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取菜单数据
        JSONObject returnJsonObject=null;
        if (null != jsonObject) {  

            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取菜单数据
            } else {
                returnJsonObject= jsonObject;
            } 
        }   

        return returnJsonObject;
    }

    /**2.2获取所有用户列表
     * 
     * @desc :一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
     *  
     * @param accessToken  调用接口凭证
     * 
     * @return
     * total    关注该公众账号的总用户数
     * count    拉取的OPENID个数,最大值为10000
     * data    列表数据,OPENID的列表
     * next_openid    拉取列表的最后一个用户的OPENID
     * 
     * @throws Exception JSONObject
     */
    public static JSONObject listAllUser(String accessToken) throws Exception {
        //1.获取请求url
        String url=LIST_ALLUSER_URL.replace("ACCESS_TOKEN", accessToken);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取菜单数据
        JSONObject returnJsonObject=null;
        if (null != jsonObject) {  

            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取菜单数据
            } else {
                returnJsonObject= jsonObject;
            } 
        }   

        return returnJsonObject;
    }


    /**
     * @desc :3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时      
     *  
     * @param accessToken  网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
     * @param openId 用户的唯一标识
     * 
     * @return
     * openid    用户的唯一标识
     * nickname    用户昵称
     * sex    用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
     * province    用户个人资料填写的省份
     * city    普通用户个人资料填写的城市
     * country    国家,如中国为CN
     * headimgurl    用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
     * privilege    用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
     * unionid    只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
     * 
     * @throws Exception JSONObject
     */
    public static JSONObject getSNSUserInfo(String accessToken,String openId ) throws Exception {
        //1.获取请求url
        String url=GET_SNS_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);

        //2.发起GET请求,获取返回结果
        JSONObject jsonObject=HttpHelper.doGet(url);
        logger.info("jsonObject:"+jsonObject.toJSONString());

        //3.解析结果,获取菜单数据
        JSONObject returnJsonObject=null;
        if (null != jsonObject) {  

            //4.错误消息处理
            if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {  
                int errCode = jsonObject.getInteger("errcode");
                String errMsg = jsonObject.getString("errmsg");
                throw new Exception("error code:"+errCode+", error message:"+errMsg); 
                //5.成功获取菜单数据
            } else {
                returnJsonObject= jsonObject;
            } 
        }   

        return returnJsonObject;


    }



}

3.IDAuthentication.jsp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page language="java" import="com.ray.weixin.gz.config.*"%>
<%@page language="java" import="com.alibaba.fastjson.JSONObject"%>
<%@page language="java" import="com.ray.weixin.gz.util.*"%>
<%@page language="java" import="com.ray.weixin.gz.service.user.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>身份认证</title>
<script src="js/jquery-3.2.1.min.js"></script>
<script type="text/javascript"
    src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

</head>
<body>



<%
         //1.接收code和state
         String code= request.getParameter("code");
         String state=request.getParameter("state");
         
         //2.获取网页授权时的accessToken 以及 openId
         JSONObject jsonObject = AuthHelper.getAccessTokenByCode(Env.APP_ID,Env.APP_SECRET, code);
         String accessToken=jsonObject.getString("access_token");
         String openId=jsonObject.getString("openid");
         
         //3.拉取用户信息
         JSONObject userInfoJsonObject =UserService.getSNSUserInfo(accessToken, openId);
         
   
%>

hello,这里是第三方应用

code=<%= code%>    <br>
state=<%= state%>      <br>
nickname=<%= userInfoJsonObject.getString("nickname") %>    <br><br>
sex=<%= userInfoJsonObject.getString("sex") %>    <br><br>
headimgurl=<%= userInfoJsonObject.getString("headimgurl") %>    <br><br>

</body>
</html>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-11-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Python+Selenium笔记(十):元素等待机制
(一) 前言 突然的资源受限或网络延迟,可能导致找不到目标元素,这时测试报告会显示测试失败。这时需要一种延时机制,来使脚本的运行速度与程序的响应速度相匹配,WebDriver为这种情况提供了隐式等待和显式等待两种机制。 (二) 隐式等待 一旦设置隐式等待时间,就会作用于这个WebDriver实例的整个生命周期(对所有的元素查找都生效),设置隐式等待时间后,Webdriver会在一定时间内持续检测和搜寻DOM,以便于查找一个或多个不是立即加载成功并可用的元素。隐式等待的默认时间是0. WebDriver使用
free赖权华
2018/04/27
3K0
Selenium2+python自动化38-显示等待(WebDriverWait)
前言: 在脚本中加入太多的sleep后会影响脚本的执行速度,虽然implicitly_wait()这种方法隐式等待方法随时一定程度上节省了很多时间。 但是一旦页面上某些js无法加载出来(其实界面元素经出来了),左上角那个图标一直转圈,这时候会一直等待的。 一、参数解释 1.这里主要有三个参数: class WebDriverWait(object):driver, timeout, poll_frequency 2.driver:返回浏览器的一个实例,这个不用多说 3.timeout:超时的总时长 4.po
上海-悠悠
2018/04/08
1.3K0
Selenium2+python自动化38-显示等待(WebDriverWait)
自动化-Selenium 3-常用API(Python版)
ActionChains类提供的鼠标事件常用方法(perform()执行所有ActionChains中存储的行为):
wangmcn
2022/07/22
1.4K0
自动化-Selenium 3-常用API(Python版)
Selenium系列(六) - 详细解读强制等待、隐式等待、显式等待的区别和源码解读
https://www.cnblogs.com/poloyy/category/1680176.html
小菠萝测试笔记
2020/06/09
4.3K1
Selenium常用的元素等待方法
日常的UI自动化测试,单步调试的时候元素可以定位到,并且可以正常操作,但是在跑测试案例流程的时候反而报错。这时就需要考虑是否界面的切换,或者功能的跳转缓慢导致元素未加载完成就执行了操作,所以我们需要加上元素等待。WebDriver提供了几种类型的等待:强制等待、显式等待和隐式等待。
Altumn
2019/10/21
1.7K0
selenium&appium中的三种等待方式---基于python
我们在实际使用selenium或者appium时,等待下个等待定位的元素出现,特别是web端加载的过程,都需要用到等待,而等待方式的设置是保证脚本稳定有效运行的一个非常重要的手段,在selenium中(appium通用)常用的等待分为显示等待WebDriverWait()、隐式等待implicitly_wait()、强制等待sleep()三种,下面我们就分别介绍一下这三种等待的区别
测试开发社区
2019/09/20
1.7K0
Python selenium — 一定要会用selenium的等待,三种等待方式解读
很多人在群里问,这个下拉框定位不到、那个弹出框定位不到…各种定位不到,其实大多数情况下就是两种问题:1 有frame,2 没有加等待。殊不知,你的代码运行速度是什么量级的,而浏览器加载渲染速度又是什么量级的,就好比闪电侠和凹凸曼约好去打怪兽,然后闪电侠打完回来之后问凹凸曼你为啥还在穿鞋没出门?凹凸曼分分中内心一万只羊驼飞过,欺负哥速度慢,哥不跟你玩了,抛个异常撂挑子了。
Python疯子
2018/09/06
2.1K0
知否知否-----selenium知多少
关于selenium,就不多介绍什么了,主要就是用来进行自动化的工具。怎样进行自动化,这才是它大放异彩的地方。下面就来看看吧!
我被狗咬了
2019/09/23
5320
知否知否-----selenium知多少
Selenium自动化测试-设置元素等待
使用sleep,需先导入time模块,import time, 然后使用time.sleep()来让程序等待多久。
可可的测试小栈
2019/11/14
1.8K0
Selenium自动化测试-设置元素等待
使用sleep,需先导入time模块,import time, 然后使用time.sleep()来让程序等待多久。
王大力测试进阶之路
2020/03/10
1.5K0
爬虫之Selenium的等待及定位
关于昨天的机器学习文章,希望能够亲自码一下,将会学到很多东西,如果觉得很好,欢迎转发,谢谢! 有关翻译贡献,可点击公众号右下角联系我,备注:翻译,或者昨日文章的阅读原文,pr到仓库中来! 关于今天的爬虫文章,则是一篇之前练习爬虫碰到的问题解决策略,希望可以帮助大家,下面一起来看吧,欢迎留言与转发!
公众号guangcity
2019/09/20
9980
爬虫之Selenium的等待及定位
Python:Selenium中三种等待方法说明
强制等待:不管浏览器元素是否加载完成,程序都得等待3秒,3秒一到,继续执行下面的代码。
Python学习者
2023/06/18
6620
Selenium4+Python3系列(六) - Selenium的三种等待,强制等待、隐式等待、显式等待
用一句通俗易懂的话就是:等待元素已被加载完全之后,再去定位该元素,就不会出现定位失败的报错了。
软件测试君
2022/12/05
3.1K0
Selenium4+Python3系列(六) - Selenium的三种等待,强制等待、隐式等待、显式等待
Selenium必须掌握的元素定位方法
Web端的UI自动化测试,目前使用比较多的就是Python+Selenium。当前一些UI自动化测试工具也是基于Selenium做开发的。 最近经常有童鞋后台询问selenium元素定位方法,其实网上学习资料很多,只要你肯动手,都可以搜的到。元素定位对于自动化测试来说是比较重要而且繁琐的一件事。接下来就来讲一下如何使用webdriver提供的基本元素定位方法。 再次声明:本站点已经和百度、必应、谷歌等各大搜索引擎达成长期的战略合作协议,你有任何疑问都可以通过以上公司提供的免费服务得到解答。
Altumn
2019/10/20
4.8K0
selenium 的显示等待与隐式等待
现在很多的网页都采用了 Ajax 技术,那么采用一般的静态爬虫技术会出现抓取不到页面的元素。比如歌曲的主页会有评论数量,一般评论数量是动态加载的。 所以这就涉及到selenium,支持各种浏览器,包括Chrome,Safari,Firefox 等主流界面式浏览器,如果你在这些浏览器里面安装一个 Selenium 的插件,那么便可以方便地实现Web界面的测试。
张凝可
2019/08/22
3.6K0
Selenium之操作浏览器、元素等待、窗体切换和弹窗处理
由于现在web端页面提供了更丰富的鼠标交互方式,因此,在做UI自动化的过程中可能会用到鼠标的右击、双击、悬停、甚至是鼠标拖动等功能。这些在WebDriver 中都是支持的,基于鼠标的相关操作方法都封装在ActionChains类中。
小博测试成长之路
2021/03/08
2K0
Selenium之操作浏览器、元素等待、窗体切换和弹窗处理
《selenium2 python 自动化测试实战》(6)——打印信息和设置等待时间
打印信息经常用的有两个: # coding: utf-8 from selenium import webdriver driver = webdriver.Firefox() driver.get("http://www.baidu.com") # 打印网页标题 title = driver.title print title # 打印当前url curr = driver.current_url print curr 打印显示为: 我们打印这些东西不是为了给自己看,而是为了做断
孟船长
2018/05/18
1.2K0
python selenium2示例 - 同步机制
前言 在使用python selenium2进行自动化测试实践的过程中,经常会遇到元素定位不到,弹出框定位不到等等各种定位不到的情况,在大多数的情况下,无非是以下两种情况: 1、有frame存在,定位前,未switch到对应的frame内 2、元素未加载完毕(从界面看已经显示),但DOM树还在load状态或在加载js 那对于这类情况,怎么解决呢? 通俗的讲法: 等待。 高大上点:解决自动化测试代码与浏览器加载渲染之间的同步问题。 下面我们分段讲述各种处理方式: 一 强制等待 这种方式简单粗暴直接有效,不
苦叶子
2018/04/04
8860
python selenium2示例 - 同步机制
Selenium
元素定位可以根据id,class等属性定位,也可以根据标签名等信息进行定位。使用定位函数后会返回一个WebElement类或一个WebElement类的列表,用于接下来的操作。
TomatoCool
2023/07/31
2400
Selenium 元素checkbox元素操作与元素等待
检测百度页面搜索按钮是否存在,存在就输入关键词“自学网 Selenium” 然后点击搜索
清风穆云
2021/08/09
1.6K0
推荐阅读
相关推荐
Python+Selenium笔记(十):元素等待机制
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • GitHub源码:https://github.com/shirayner/weixin_gz
  • 一、本节要点
    • 1.网页授权回调域名
    • 2. 获取code
    •  3.通过code换取网页授权access_token
    • 4.通过网页授权access_token 拉取用户信息
  • 二、代码实现
    • 1.Token工具类—AuthHelper
    • 2.用户管理业务类—UserService
    • 3.IDAuthentication.jsp
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档