admin管理员组

文章数量:1530013

微信公众号 网页授权登入

官网地址:

https://developers.weixin.qq/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

关于网页授权的两种scope的区别说明

1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)

2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。

关于网页授权access_token和普通access_token的区别

1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;

2、其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。

关于特殊场景下的静默授权

1、上面已经提到,对于以snsapi_base为scope的网页授权,就静默授权的,用户无感知;

2、对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。

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

1、引导用户进入授权页面同意授权,获取code

2、通过code换取网页授权access_token(与基础支持中的access_token不同)

3、如果需要,开发者可以刷新网页授权access_token,避免过期

4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

目录

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

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

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

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

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

参数说明

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

参数说明

参数是否必须说明
appid公众号的唯一标识
secret公众号的appsecret
code填写第一步获取的code参数
grant_type填写为authorization_code
参数描述
openid用户的唯一标识
nickname用户昵称
sex用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
province用户个人资料填写的省份
city普通用户个人资料填写的城市
country国家,如中国为CN
headimgurl用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
privilege用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
unionid只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。

实践

controller

package com.kuang.controller;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.kuang.pojo.ResultBean;
import com.kuang.pojo.UserBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: Abe
 * Date: 2020/12/5 22:36
 */
@Controller
@RequestMapping("/wx/oauth")
@Slf4j
public class WxOauthController {

    @Value("${wechat.wx.appid}")
    private String appid;
    @Value("${wechat.wx.secret}")
    private String secret;


    /**
     * 构造授权链接
     */
    @GetMapping("")
    public String oauth(HttpServletRequest request) {

        //回调地址
        String redirect_uri = "http://127.0.0.1:8080/wx/oauth/oAuth2Url";;
        try {
            //urlEncode 对链接进行处理
            redirect_uri = java.net.URLEncoder.encode(redirect_uri, "utf-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        String oauth2Url = "https://open.weixin.qq/connect/oauth2/authorize?appid="+appid+"&redirect_uri="+redirect_uri
                +"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
        //构造好的链接
        return "redirect:" + oauth2Url;
    }


    /**
     * 回调地址
     */
    @GetMapping("/oAuth2Url")
    @ResponseBody
    public Object oAuth2Url(String code) {
        //获取access_token
        //这边获得的access_token最好是要使用redis或者其他缓存机制缓存起来
        //不要每次每次都去请求获取access_token,因为请求接口时有限制次数的
        //这样每次进来都先判断一波access_token是否存在
        //我这边是为了省事,同时也是单纯为了测试,所以没有做缓存,实际开发中一定要做缓存
        String url = " https://api.weixin.qq/sns/oauth2/access_token";
        //发起请求
        HashMap<String, Object> parm = new HashMap<>();
        parm.put("appid", appid);
        parm.put("secret", secret);
        parm.put("code", code);
        parm.put("grant_type", "authorization_code");
        String s = HttpUtil.get(url, parm);
        log.info("token=" + s);
        ResultBean resultBean = JSONUtil.toBean(s, ResultBean.class);
        if(resultBean.getAccess_token() != null) {//证明请求成功
            //获取用户信息
            String userUrl = "https://api.weixin.qq/sns/userinfo";
            HashMap<String, Object> parmData = new HashMap<>();
            parmData.put("access_token", resultBean.getAccess_token());
            parmData.put("openid", resultBean.getOpenid());
            parmData.put("lang", "zh_CN");
            String userJson = HttpUtil.get(userUrl, parmData);
            log.info(userJson + "===");
            UserBean userBean = JSONUtil.toBean(userJson, UserBean.class);
            log.info(userBean+ "用户的信息");
            return userBean;
        }

        return null;
    }

}

pojo

package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Author: Abe
 * Date: 2020/12/5 22:57
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultBean {
    private String access_token;
    private Long expires_in;
    private String refresh_token;
    private String openid;
    private String scope;
}
package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Author: Abe
 * Date: 2020/12/5 23:04
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserBean {
    private String openid;
    private String nickname;
    private String sex;
    private String province;
    private String city;
    private String country;
    private String headimgurl;
    private String[] privilege;
    private String unionid;
}

maven

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache/POM/4.0.0" xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache/POM/4.0.0 https://maven.apache/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.kuang</groupId>
    <artifactId>spring-wx-oauth</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-wx-oauth</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

wechat:
  wx:
    appid: 你的公众号的唯一标识
    secret: 公众号的appsecret

总结

  1. 测试公众号的官网地址 https://mp.weixin.qq/debug/cgi-bin/sandbox?t=sandbox/login,
  2. 体验接口权限便->网页服务->网页账号->授权回调页面域名.在测试公众号的话,是可以设置ip地址,不过正式的公众号必须是域名。设置这个ip地址的时候需要注意,要带上你的项目的端口号,比如我设置的回调地址就是 127.0.0.1:8080
  3. scope的值为snsapi_base只能获取到openid,值为snsapi_userinfo才可以获取用户的基本信息,我上面的demo就是使用snsapi_userinfo

本文标签: 登入公众网页