通过 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_in | access_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)
关键注意事项
- code 只能使用一次,5 分钟未用自动过期。调试时不要重复刷新同一个 code 的页面。
- 网页授权 access_token 与基础 access_token 是两套东西,不要混用。基础 access_token 用于模板消息、自定义菜单等接口;网页授权 access_token 仅用于获取用户信息。
- secret 和 access_token 不要传到客户端,所有换取和刷新操作都在服务器端完成。
- 如果 scope 是
snsapi_base,到这一步就已经拿到了openid,不需要再走获取用户信息的步骤。 - 如果 scope 是
snsapi_userinfo,接下来还需要用webAccessToken + openid调用获取用户基本信息接口,这个我们下一步再实现。
Previous: 15-微信网页授权的理解和第一步-用户同意授权获取
Next: 17-Token使用缓存的方式来存储