2016-01-14 13:55:49 HinstenyHisoka 阅读数 5926

当我们进行微信平台相关内容开发时,如果想做一些针对微信用户进行一些信息获取及消息推送,那我们第一步先要拿到微信用户的OPENID(用户唯一标识,建立在一个公众号与一个微信用户之间,即针对一个公众号,所有的微信用户都享有一个独立不变的标识);


1 . 如果微信用户已经关注自己的公众号, 那可以通过微信接口里面的用户管理模板直接获取到对应公众号的所有已关注用户OPENID的列表;
1). 在调用所有的微信接口之前,我们先要请求授权,拿到access_token

    @Getter
    @Config("wechat.appid")
    private static String WECHATAPPID;

    @Getter
    @Config("wechat.appsecret")
    private static String WECHATAPPSECRET;

    public static final String ACCESS_TOKEN = "access_token";
    public final static String WECHATACCESSTOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=";
        /**
     * <p>
     * 成功: {"access_token":"ACCESS_TOKEN","expires_in":7200}
     * </p>
     * <p>
     * 失败: {"errcode":40013,"errmsg":"invalid appid"}
     * </p>
     * @return 如果没有获取到有效的凭据,就返回 null
     */
    private static Map getWechatAPPAccessTokenFromWeChat() {
        StringBuilder accessTokenUrl = new StringBuilder().append(WECHATACCESSTOKEN).append(WECHATAPPID)
                        .append("&secret=").append(WECHATAPPSECRET);
        Map result = HttpClientUtil.readHttpContent(accessTokenUrl.toString());
        if (result != null && result.get(ACCESS_TOKEN) != null)
            return result;
        return null;
    }

    //HttpClientUtil.class static method
    /**
     * get json content and transform to Map from the urlStr
     * If occuer one error just return null.
     * @param urlStr
     * @return
     */
    public static Map<String,Object> readHttpContent(String urlStr){
        Map<String, Object> result = null;
        HttpEntity httpEntity = null;
        try {
            HttpResponse response = Request.Get(urlStr).execute().returnResponse();
            httpEntity = response.getEntity();
        }catch (IOException e) {
            logger.error("Get resouse from {} had occurred an error: {}", urlStr, e.toString());
            return result;
        }
        try (
            InputStream in = httpEntity.getContent();
        ){
            ObjectMapper mapper = new ObjectMapper();
            result = mapper.readValue(in, HashMap.class);
        }catch (IOException e) {
            logger.error("Get json content from {} had occurred an error: {}", urlStr, e.toString());
            return result;
        }
        return result;
    }

2). 使用前面得到的access_token获取公众号的微信关注用户列表

    public static final String ERRMSG = "errmsg";
    public final static String WECHATUSERLISTURL = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=";
    /**
     *<p>
     * 获取成功:{
     *  "total":23000,
     *  "count":10000,
     *  "data":{"
     *    openid":[
     *      "OPENID1",
     *      "OPENID2",
     *      ...,
     *      "OPENID10000"
     *    ]
     *  },
     *  "next_openid":"OPENID10000"
     *  }
     *</p>
     *
     *<p>
     * 获取失败:{"errcode":40013,"errmsg":"invalid appid"}
     *</p>
     *
     *
     * 获取微信公众帐号的关注者列表(wechat user openID),每次最多10000个
     *
     * @param accessToken
     * @param next_openid: 没有此参数,则默认从关注列表的第一个开始获取
     * @return
     */
    public static Map getWechatUserOpenIDList(String accessToken, String next_openid) {
        StringBuilder urlB = new StringBuilder().append(WECHATUSERLISTURL).append(accessToken);
        if (!Strings.isBlank(next_openid))
            urlB.append("&next_openid=").append(next_openid);
        Map result = HttpClientUtil.readHttpContent(urlB.toString());
        if (result != null && result.get(ERRMSG) == null)
            return result;
        return null;
    }
采用方法一,到此便得到了用户openID列表,可以进行后面获取微信用户信息及向用户推送模板消息等;

2 . 无论微信用户是否关注自己的公众号, 当微信用户访问我们的web站点时(通过微信内置浏览器),我们可以通过页面授权的方式拿到微信用户的OpendID(页面授权需要跳转到微信服务器拿到oauth_code然后再换取access_token及OpendID);
1). 为我们的web站点服务添加一个filter,拦截来自微信浏览器的请求,进行302跳转到微信站点,拿到授权码再回调回来;

public class WechatFilter implements Filter {

    private static final Logger logger             = LoggerFactory.getLogger(WechatFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        if (response.isCommitted()) {
            chain.doFilter(request, response);
            return;
        }
        //判断请求是否来自微信浏览器
        if (!WebUtil.isWechatRequest(httpRequest)) {
            chain.doFilter(request, response);
            return;
        }
        String requestURL = WebUtil.getRequsetUrl(httpRequest, true, true);
        logger.debug("Request from wechat client:{}", requestURL);
        HttpSession session = httpRequest.getSession();
        String weChatOpenId = (String) session.getAttribute(WeChatManager.WECHATOPENID);
        if (weChatOpenId == null) {
            if (httpRequest.getParameter(WeChatManager.CODE) == null) {
                StringBuilder url = new StringBuilder("http://").append(WebUtil.getRequsetUrl(httpRequest, true, true));
                response.reset();
                ((HttpServletResponse) response).sendRedirect(url.toString());
                return;
            } else {
                String oauthCode = httpRequest.getParameter(WeChatManager.CODE);
                if (!Strings.isBlank(oauthCode)) {
                    Map<String, Object> oauth_data = WeChatPageInterface.getWechatPageAccessToken(oauthCode);
                    weChatOpenId = oauthCode != null && oauth_data.get(WeChatManager.OPENID) != null ? (String) oauth_data.get(WeChatManager.OPENID) : null;
                    session.setAttribute(WeChatManager.WECHATOPENID, weChatOpenId);
                } else {
                    logger.warn("The oauth_code is empty!");
                }
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

}
    //WeChatPageInterface.class static method
    /**
     * <p>
     * 微信获取授权成功:{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN",
     * "openid":"OPENID", "scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
     * </p>
     * <p>
     * 微信获取授权失败:{"errcode":40029,"errmsg":"invalid code"}
     * </p>
     *
     * 请求微信公众号的网页授权,得到用户OpenID和access_token
     * 微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证( 网页授权access_token),
     * 通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;
     *
     * @return 如果没有获取到有效的凭据,就返回 null
     */
    public static Map<String, Object> getWechatPageAccessToken(String oauthCode) {
        StringBuilder accessTokenUrl = new StringBuilder().append(WeChatManager.weChatAuthAccessTokenPage).append(WeChatManager.getWECHATAPPID())
                        .append("&secret=").append(WeChatManager.getWECHATAPPSECRET()).append("&code=")
                        .append(oauthCode).append("&grant_type=").append("authorization_code");
        Map<String, Object> accessToken = HttpClientUtil.readHttpContent(accessTokenUrl.toString());
        if (accessToken != null && accessToken.get(WeChatManager.ACCESS_TOKEN) != null) {
            return accessToken;
        }
        return null;
    }

至此,我们通过两种方式都可以获取微信用户的OpenID了,至于采用哪一种可以根据实际业务环境;

PS: OpenID是介于微信用户与公众账号之间恒定不变的,所以可以进行三方持久化存储;

2014-11-02 11:02:07 fuyifang 阅读数 175920

在微信开发时候在做消息接口交互的时候需要使用带微信加密ID(OpenId),下面讲讲述2中类型方式获取微信OpenID,接收事件推送方式和网页授权获取用户基本信息方式获取。

1、通过接收被动消息方式获取OpenId(接收事件推送方式),以下事件中都可以获取到OpenID

关注/取消关注事件

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。

微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次

关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

推送XML数据包示例:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,subscribe(订阅)、unsubscribe(取消订阅)

使用网页调试工具调试该接口

扫描带参数二维码事件

用户扫描带场景值二维码时,可能推送以下两种事件:

  1. 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
  2. 如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。

1. 用户未关注时,进行关注后的事件推送

推送XML数据包示例:

<xml><ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[qrscene_123123]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,subscribe
EventKey事件KEY值,qrscene_为前缀,后面为二维码的参数值
Ticket二维码的ticket,可用来换取二维码图片

2. 用户已关注时的事件推送

推送XML数据包示例:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[SCAN]]></Event>
<EventKey><![CDATA[SCENE_VALUE]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,SCAN
EventKey事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
Ticket二维码的ticket,可用来换取二维码图片

使用网页调试工具调试该接口

上报地理位置事件

用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置,公众号可以在公众平台网站中修改以上设置。上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。

推送XML数据包示例:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[LOCATION]]></Event>
<Latitude>23.137466</Latitude>
<Longitude>113.352425</Longitude>
<Precision>119.385040</Precision>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,LOCATION
Latitude地理位置纬度
Longitude地理位置经度
Precision地理位置精度

使用网页调试工具调试该接口

自定义菜单事件

用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。

点击菜单拉取消息时的事件推送

推送XML数据包示例:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,CLICK
EventKey事件KEY值,与自定义菜单接口中KEY值对应


点击菜单跳转链接时的事件推送

推送XML数据包示例:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[VIEW]]></Event>
<EventKey><![CDATA[www.qq.com]]></EventKey>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,VIEW
EventKey事件KEY值,设置的跳转URL

使用网页调试工具调试该接口

 以上信息摘自微信公众平台接收事件推送章节。点击查看原始帮助文档-接收事件推送


2、通过第三方网页授权方式获取OpenID,采用第三方网页授权(OAuth2.0授权登录)

如果用户在微信中(Web微信除外)访问公众号的第三方网页,公众号开发者可以通过此接口获取当前用户基本信息(包括昵称、性别、城市、国家)。利用用户信息,可以实现体验优化、用户来源统计、帐号绑定、用户身份鉴权等功能。请注意,“获取用户基本信息接口是在用户和公众号产生消息交互时,才能根据用户OpenID获取用户基本信息,而网页授权的方式获取用户基本信息,则无需消息交互,只是用户进入到公众号的网页,就可弹出请求用户授权的界面,用户授权后,就可获得其基本信息(此过程甚至不需要用户已经关注公众号。)”

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

在微信公众号请求用户网页授权之前,开发者需要先到公众平台网站的我的服务页中配置授权回调域名。请注意,这里填写的域名不要加http://

关于配置授权回调域名的说明:

授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.htmlhttp://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.comhttp://music.qq.comhttp://qq.com  无法进行OAuth2.0鉴权。

具体而言,网页授权流程分为四步:

  1. 引导用户进入授权页面同意授权,获取code
  2. 通过code换取网页授权access_token(与基础支持中的access_token不同)
  3. 如果需要,开发者可以刷新网页授权access_token,避免过期
  4. 通过网页授权access_token和openid获取用户基本信息

目录

[隐藏]

第一步:用户同意授权,获取code

在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认带有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
参考链接(请在微信客户端中打开此链接体验)
Scope为snsapi_base
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=http%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect
Scope为snsapi_userinfo
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

参数说明

参数是否必须说明
appid公众号的唯一标识
redirect_uri授权后重定向的回调链接地址,请使用urlencode对链接进行处理
response_type返回类型,请填写code
scope应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息
state重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值
#wechat_redirect无论直接打开还是做页面302重定向时候,必须带此参数

下图为scope等于snsapi_userinfo时的授权页面:

网页授权

用户同意授权后

如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE

code说明 :
code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

第二步:通过code换取网页授权access_token

首先请注意,这里通过code换取的网页授权access_token,与基础支持中的access_token不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

请求方法

获取code后,请求以下链接获取access_token: 
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数是否必须说明
appid公众号的唯一标识
secret公众号的appsecret
code填写第一步获取的code参数
grant_type填写为authorization_code

返回说明

正确时返回的JSON数据包如下:

{
   "access_token":"ACCESS_TOKEN",
   "expires_in":7200,
   "refresh_token":"REFRESH_TOKEN",
   "openid":"OPENID",
   "scope":"SCOPE"
}
参数描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_inaccess_token接口调用凭证超时时间,单位(秒)
refresh_token用户刷新access_token
openid用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
scope用户授权的作用域,使用逗号(,)分隔


错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

全局返回码说明

第三步:刷新access_token(如果需要)

由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。

请求方法

获取第二步的refresh_token后,请求以下链接获取access_token: 
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
参数是否必须说明
appid公众号的唯一标识
grant_type填写为refresh_token
refresh_token填写通过access_token获取到的refresh_token参数

返回说明

正确时返回的JSON数据包如下:

{
   "access_token":"ACCESS_TOKEN",
   "expires_in":7200,
   "refresh_token":"REFRESH_TOKEN",
   "openid":"OPENID",
   "scope":"SCOPE"
}
参数描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_inaccess_token接口调用凭证超时时间,单位(秒)
refresh_token用户刷新access_token
openid用户唯一标识
scope用户授权的作用域,使用逗号(,)分隔


错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

全局返回码说明

第四步:拉取用户信息(需scope为 snsapi_userinfo)

如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。

请求方法

http:GET(请使用https协议)
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

参数说明

参数描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid用户的唯一标识
lang返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

返回说明

正确时返回的JSON数据包如下:

{
   "openid":" OPENID",
   " nickname": NICKNAME,
   "sex":"1",
   "province":"PROVINCE"
   "city":"CITY",
   "country":"COUNTRY",
    "headimgurl":    "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", 
	"privilege":[
	"PRIVILEGE1"
	"PRIVILEGE2"
    ]
}
参数描述
openid用户的唯一标识
nickname用户昵称
sex用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
province用户个人资料填写的省份
city普通用户个人资料填写的城市
country国家,如中国为CN
headimgurl用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
privilege用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)


错误时微信会返回JSON数据包如下(示例为openid无效):

{"errcode":40003,"errmsg":" invalid openid "}

全局返回码说明

附:检验授权凭证(access_token)是否有效

请求方法

http:GET(请使用https协议)
https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

参数说明

参数描述
access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid用户的唯一标识

返回说明

正确的Json返回结果:

{ "errcode":0,"errmsg":"ok"}

错误时的Json返回示例:

{ "errcode":40003,"errmsg":"invalid openid"}

 以上信息摘自微信公众平台网页授权获取用户基本信息章节。点击查看原始帮助文档-网页授权获取用户基本信息


更多关注付义方技术博客:http://blog.csdn.net/fuyifang 本人新浪微博:http://weibo.com/i/1741159542


2015-04-28 19:28:39 fansongy 阅读数 9687


文章作者:松阳

本文出自 阿修罗道,禁止用于商业用途,转载请注明出处。  

原文链接:http://blog.csdn.net/fansongy/article/details/45340951







网页授权

微信开发时,我们总是想要尽可能多的活动用户的信息。但微信官方和用户本身,又不想暴露这些信息。搞来搞去,就出现了很多奇形怪状的规则和交互方式。微信网页授权就是其中之一,它可以为我们提供获取用户OpenID途径。做到悄悄的进村,开枪的不要。

流程说明

这个流程其实也不复杂。首先用户访问 https://open.weixin.qq.com/connect/oauth2/authorize 这个连接,链接后面带着appid,我们要跳转的链接名称,以及一个自定义变量。当用户访问时,微信服务器会跳转回我们的链接,并将用户的openID传回来。官方说明如下:

在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。官方链接在这里

当然随随便便给你用户的openID是有条件的:保护费交一下。实名认证少不了滴。

接口设计

有了这个我们就可以使用很多授权页面了。如果你只要用户的openID,是不会出现那个恶心人的绿色界面的。如果用户未关注你的服务号,并且你还想要昵称和头像,就会出现那个“我是贼”的绿色页面。上面写明了要昵称和头像的授权,虽然我也知道没啥后招,但凡是出现这个页面的,我都毫不犹豫的关掉了

为了避免设计很多乱七八糟的Oauth接口,我建议只使用一个接口,然后通过state的值来做逻辑判断的标准,更改程序返回的页面。

实现

首先还是那句话,实名认证,没这个,接口啥的免谈。

然后编写一个统一的Oauth接口。

@RequestMapping(value="/authIntf")
public void authLogin(HttpServletRequest request,HttpServletResponse response,HttpSession session) throws IOException{
    String redirectURL="http://blog.csnd.net/fansongy";
    String code = request.getParameter("code");
    if(code == null ||code.length() == 0){
        logger.error("can't get param code from auth request!");
    }
    String actionType =request.getParameter("state");
    if(actionType == null || actionType.length() == 0){
        logger.error("can't get param code from auth request!");
    }
    String userOpenId = wxAuthService.getUserOpenID(code);
    if(userOpenId != null && userOpenId.length()>0) {
        redirectURL = loginAndJumpBack(userOpenId, actionType);
    }else {
        logger.info("Can't find openId in authLogin");
    }
    response.sendRedirect(redirectURL);
}

public String loginAndJumpBack(String fromUserName, String actionType) {
    //your logic
    return "http://www.baidu.com";
}

部署

在微信服务号的后台设置合法的域名,具体做法可以参考官方文档:

在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的开发者中心页配置授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加http://等协议头;

最终部署时,建议先更新服务,然后在微信中通过链接的方式测试,测试完成后,在添加微信入口,比如菜单点击事件。

如果你觉得这篇文章对你有帮助,可以顺手点个,不但不会喜当爹,还能让更多人能看到它... 

2018-12-07 10:29:24 qq_15098375 阅读数 572

要获取微信openid输入redirect_uri之后//变为黑线整个网址不能访问

具体展开之后变为:

访问不能成功,目前不知道怎么解决。

2018-11-07 15:02:10 qq_31122833 阅读数 3855

在上一篇的基础上,有一个地方是需要去微信公众平台设置的(如果你这个url需要获取用户openid的话!如果不需要获取可以无视)

登录微信公众平台-->公众号设置-->选择功能设置-->设置网页授权域名(为微信认为安全的地址,不用精确到方法,但是你需要将一个文本密钥放入对应地址下,微信会在这个地址校验密钥。密钥微信会给你下载)

我放在这里(这是我op项目下的resources/static/open)对应op/open:

这些做完之后,点击保存,微信会给你返回结果。我这边是成功了!如果失败:会有错误信息,一般是找不到那个密钥,看看你的位置是否放正确了!

这些事情做完之后,我们回到上一篇:

组装菜单数据方法getMenu()那:

String redirect_uri = "http://www.你的服务器回调地址.com/op/open/openArticle";

这个地址:BaseAPI.OPEN_URI+"/connect/oauth2/authorize?appid="+ WeiXinUtil.APPID+"&redirect_uri="+redirect_uri+"?category=1&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
它的完整地址是:
https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ WeiXinUtil.APPID+"&redirect_uri="+redirect_uri+"?category=1&response_type=code&scope=snsapi_base&state=1#wechat_redirect
其中appid不用我说了吧。别的东西都不用管,你先看redirect_uri
这个地址能否调用你的项目接口
例如我的项目接口有这个方法:
/**
  * 公共文章界面
  * @param map
  * @return
  */
 @RequestMapping(value = "/open/openArticle")
 public String openArticle(ModelMap map,HttpServletRequest request) throws Exception{
     String code = request.getParameter("code");//页面授权获取的code用以交换 openid
     String openId = OAuthGetOpenid(code);//OAuth获取用户openid区分是哪个用户请求登录W3
     map.put("title", "公共文章界面");
     map.put("path", path);
     map.put("openId",openId);
     map.put("category",category);
    
     return "openArticle";
    }

/**
  * 通过页面OAuth授权,用code获取openid
  *
  * @param code
  * @return
  */
 public String OAuthGetOpenid(String code) throws Exception{
     JSONObject json = new JSONObject();
     String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+WeiXinUtil.APPID+"&secret="+WeiXinUtil.APPSECRET+"&code=" + code + "&grant_type=authorization_code";
     String outputStr = "";
     json = WeiXinUtil.doPostStr(requestUrl, outputStr);
     String openid = json.getString("openid");
     logger.info(json+"---------json--------openid-----------"+openid);
     return openid;
 }

到这就完成了。点击菜单按钮之后,我这边可以成功获取到用户的openid,并且成功跳转到指定url页面

微信openid获取

阅读数 599

没有更多推荐了,返回首页