百度统计(百度账号)授权回调页设置后跳转到百度账号登录报错:redirect_uri_mismatch 百度回调地址错误
如题,在接入百度统计接口数据时发现,使用百度账号接口的 百度账号登录
流程报错:错误代码:redirect_uri_mismatch,错误信息:Invali redirect uri,详细描述:授权回调地址错误。具体内容请开发者参考
“redirect uri”验证方式。
按照百度的帮助文档去定位错误原因,然后通过 百度账号接口说明 中的 百度开发者中心控制台 登录到项目工程列表,里面是之前创建的一些项目,用到了百度的 API 而申请的。按照指示,点击安全设置进入到以下的页面:
在 授权回调页
中添加了回调地址(主要是为了接受百度授权账号登录成功后跳转携带的 code 参数),然后去尝试再次请求,依然报错。就这样折腾了半天各种方法都尝试之后,想着去搜索一下这个问题,看是否有解决方案。直接搜索 redirect_uri_mismatch
出来的都是新浪微博授权登录失败之类的问题。换成 百度统计 授权回调页设置
之后,终于找到了一个匹配度很高的方法:百度回调地址问题 - cnblogs。
里面加粗强调了一件事:修改 redirect url
地址(回调地址必须填写为 bdconnect://success
, 不然会报错)。在安全设置中的回调地址依然填写之前的,修改的是 百度账号登录
以及之后所有接口参数中用到的 redirect_uri 参数。
尝试修改之后再次访问,发现页面没有报错了,跳转到了百度账号授权登录页面。登录状态下直接点击授权登录,然后页面加载了一下就停了。通过浏览器控制台发现,授权登录成功后,页面跳转到 bdconnect://success?code=xxx
了。code 是携带了,但没有走我的回调地址,也就拿不到这个 code。回头一想,我回调地址也没传给他呀,用我的回调地址,则授权登录无法进行,用这个 bdconnect://success
可以授权成功,但我拿不到 code。看到这个解决方案还是 2014 年写的,这么长时间了百度还是没有更新这个 bug,真 TM 坑。
最后取了一个折中的方法,通过页面授权登录,控制台请求 response 中拿到 code,然后回调地址手动输入 code 参数使其加入到缓存中,从而跳过获取授权码的这个过程。后续的 access_token 和 refresh_token 可以循环跑起来,就不需要授权码了。
以下是我封装的入口文件,参考了获取微信 access_token 信息的模板(本身基于 destoon 框架):
统计初始化文件 init.inc.php
require DT_ROOT.'/xxx/config.inc.php';
$session = new dsession();
class tongji {
var $code;
var $access_token;
var $refresh_token;
var $current_url;
function __construct() {
global $DT_TIME;
$this->time = $DT_TIME;
// $this->current_url = DT_PATH . 'xxx/index.php';
$this->current_url = 'bdconnect://success';
}
function tongji() {
$this->__construct();
}
function http_get($url) {
$rec = dcurl($url);
$arr = json_decode($rec, true);
return $arr ? $arr : array();
}
function http_post($url, $par) {
$rec = dcurl($url, $par);
$arr = json_decode($rec, true);
return $arr ? $arr : array();
}
function get_code() {
global $dc;
$tongji_code = $dc->get('tongji_code');
if($tongji_code) {
return $tongji_code;
}
// 4. 百度账号登录
$url = 'http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id='.TONGJI_APIKEY.'&redirect_uri='.$this->current_url.'&scope=basic&display=popup';
dheader($url);
return '';
}
function get_token() {
global $dc;
// code 获取存在问题,现直接通过外部输入 code
$this->code = $this->get_code();
if (!$this->code) {
exit();
}
// 5. 通过身份验证(code)获取 ACCESS_TOKEN
$url = 'http://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code='.$this->code.'&client_id='.TONGJI_APIKEY.'&client_secret='.TONGJI_SECRETKEY.'&redirect_uri='.$this->current_url;
$arr = $this->http_get($url);
$dc->set('tongji_access_token', $arr['access_token'], 2592000);
$dc->set('tongji_refresh_token', $arr['refresh_token'], 311040000);
return isset($arr['access_token']) ? $arr['access_token'] : '';
}
function refresh_token() {
global $dc;
$this->refresh_token = $dc->get('tongji_refresh_token');
if (!$this->refresh_token) {
$this->get_token();
}
$url = 'http://openapi.baidu.com/oauth/2.0/token?grant_type=refresh_token&refresh_token='.$this->refresh_token.'&client_id='.TONGJI_APIKEY.'&client_secret='.TONGJI_SECRETKEY;
$arr = $this->http_get($url);
$dc->set('tongji_access_token', $arr['access_token'], 2592000);
$dc->set('tongji_refresh_token', $arr['refresh_token'], 311040000);
return isset($arr['access_token']) ? $arr['access_token'] : '';
}
function getSiteList() {
$url = 'https://openapi.baidu.com/rest/2.0/tongji/config/getSiteList?access_token='.$this->access_token;
return $this->http_get($url);
}
}
$tj = new tongji;
$tj->access_token = $dc->get('tongji_access_token');
if(!$tj->access_token) {
// 直接更新 access_token
$tj->access_token = $tj->refresh_token();
}
配置文件 config.inc.php
define('TONGJI_ID', 'xx');
define('TONGJI_APIKEY', 'xx');
define('TONGJI_SECRETKEY', 'xx');
回调地址 index.php
// 百度统计接口
require '../../common.inc.php';
require DT_ROOT.'/api/baidu/init.inc.php';
/**
* API 文档地址
* https://tongji.baidu.com/api/manual/Chapter2/openapi.html
* 省略前面申请百度账号和创建工程获取API Key 与Secret Key 的过程
* 从 4. 百度账号登录 开始
*/
if ($code) {
// 存在 code 表示登录成功后跳转回调,当前地址即为回调 URL
// 5. 通过身份验证(code)获取 ACCESS_TOKEN
$dc->set('tongji_code', $code, 311040000);
dheader($tj->current_url);
}
echo $tj->access_token;
然后拿到公司百度统计的账号,想着登录进去再创建新的工程,拿到 API Key 和 Secret Key。结果进去发现,公司用的是百度商业账号,接口也跟百度账号完成不一样,瞬间懵逼了。这意味着我之前都是在浪费时间,现在对接接口还得从头来过。
好在百度商业账号的接口非常简单好接,不需要 API Key 和 Secret Key,用户名和密码现成的,token 在百度统计后台的管理菜单下,左侧 其他设置
中的 数据导出服务
中获取。点击开通服务,token 就会显示在页面上了,百度账号就没有这个东西了。
总结:下次对接接口的时候,一定要确定自己对接的是与目标功能匹配的接口,否则再多的努力都是白费功夫。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。