16-微信网页授权-通过code换取网页授权access_token

通过 code 换取网页授权 access_token

首先请注意,这里通过 code 换取的是一个特殊的网页授权 access_token,与基础支持中的 access_token(用于调用其他接口)不同。

公众号可通过下述接口来获取网页授权 access_token。如果网页授权的作用域为 snsapi_base,则本步骤中获取到网页授权 access_token 的同时,也获取到了 openid,snsapi_base 式的网页授权流程即到此为止。

安全提醒:由于公众号的 secret 和获取到的 access_token 安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新 access_token、通过 access_token 获取用户信息等步骤,也必须从服务器发起。

请求方法

获取 code 后,请求以下链接获取 access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_codeCode language: JavaScript (javascript)

参数说明

参数是否必须说明
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"
}Code language: JSON / JSON with Comments (json)
参数描述
access_token网页授权接口调用凭证,注意:此 access_token 与基础支持的 access_token 不同
expires_inaccess_token 接口调用凭证超时时间,单位(秒)
refresh_token用户刷新 access_token
openid用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的 OpenID
scope用户授权的作用域,使用逗号(,)分隔

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

{"errcode":40029,"errmsg":"invalid code"}Code language: JSON / JSON with Comments (json)

在 Manage 控制器中获取 code 并换取网页授权 access_token

用户同意授权后,微信会跳转回 redirect_uri,并附带 code 和 state 参数。我们在 Manage 控制器中接收这个 code,然后调用接口换取网页授权 access_token。

public class HomeController : Controller
{
    public ActionResult Manage(string code, string state)
    {
        if (string.IsNullOrEmpty(code))
        {
            return Content("未获取到授权code");
        }

        // 第一步:用 code 换取网页授权 access_token
        var url = string.Format(
            "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code",
            "wx51ebd98e1d633db6",
            "42a5564582bda88104367ea5851c9265",
            code
        );

        var json = HtmlHelper.HttpGet(url);
        var tokenResult = JsonHelper.DeserializeJsonToObject<dynamic>(json);

        // 判断是否返回错误
        if (tokenResult.errcode != null)
        {
            return Content("获取网页授权access_token失败:" + tokenResult.errmsg);
        }

        // 拿到网页授权 access_token 和 openid
        string webAccessToken = tokenResult.access_token;
        string openid = tokenResult.openid;
        string refreshToken = tokenResult.refresh_token;
        string scope = tokenResult.scope;

        // 可以将 webAccessToken、openid 存入 Session 或缓存,供后续使用
        Session["WebAccessToken"] = webAccessToken;
        Session["OAuthOpenId"] = openid;

        // 第二步(下一步):通过 webAccessToken 和 openid 获取用户信息
        // 这里先返回获取到的 token 信息,验证流程是否走通
        return Json(new
        {
            webAccessToken,
            openid,
            scope,
            tip = "接下来可以用 webAccessToken + openid 调用获取用户信息接口"
        }, JsonRequestBehavior.AllowGet);
    }
}Code language: HTML, XML (xml)

关键注意事项

  1. code 只能使用一次,5 分钟未用自动过期。调试时不要重复刷新同一个 code 的页面。
  2. 网页授权 access_token 与基础 access_token 是两套东西,不要混用。基础 access_token 用于模板消息、自定义菜单等接口;网页授权 access_token 仅用于获取用户信息。
  3. secret 和 access_token 不要传到客户端,所有换取和刷新操作都在服务器端完成。
  4. 如果 scope 是 snsapi_base,到这一步就已经拿到了 openid,不需要再走获取用户信息的步骤。
  5. 如果 scope 是 snsapi_userinfo,接下来还需要用 webAccessToken + openid 调用获取用户基本信息接口,这个我们下一步再实现。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注