Fitbit授权后PHP获取用户ID及用授权码发POST请求的问题
Fitbit授权流程问题解决:获取访问令牌与用户登录状态处理
一、修正授权码兑换访问令牌的POST请求
你当前代码在兑换令牌环节存在URL错误、参数缺失、请求头未设置的问题,以下是正确实现逻辑:
- 完善HTTP请求函数,支持自定义请求头
- 按Fitbit要求构造令牌请求参数,包含
grant_type、code、redirect_uri、code_verifier必填项 - 添加Basic认证请求头,使用base64编码的
client_id:client_secret作为授权凭证
二、处理用户登录状态与显示用户ID
Fitbit返回的令牌响应中包含user_id字段,将其存入Session即可标识用户登录状态,后续通过Session判断并展示用户ID。
修改后的完整PHP代码
<?php session_start(); // 完善HTTP请求函数,支持POST请求头设置 function http($url, $params = false, $headers = []) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 设置默认请求头 $defaultHeaders = ['Content-Type: application/x-www-form-urlencoded']; if (!empty($headers)) { $defaultHeaders = array_merge($defaultHeaders, $headers); } curl_setopt($ch, CURLOPT_HTTPHEADER, $defaultHeaders); if ($params) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); } $response = curl_exec($ch); curl_close($ch); return json_decode($response); } $client_id = 'CLIENT_ID_VALUE'; $client_secret = 'CLIENT_SECRET_VALUE'; $redirect_uri = 'https://localhost/DailyAppleFit/'; $token_url = 'https://api.fitbit.com/oauth2/token'; // 生成Basic认证字符串 $auth_header = 'Basic ' . base64_encode("{$client_id}:{$client_secret}"); // 已登录状态处理 if (isset($_SESSION['user_id'])) { echo '<p>已登录,用户ID:</p>'; echo '<p>' . $_SESSION['user_id'] . '</p>'; echo '<p><a href="/?logout">退出登录</a></p>'; die(); } // 退出登录处理 if (isset($_GET['logout'])) { unset($_SESSION['user_id'], $_SESSION['access_token']); header('Location: /'); die(); } // 处理授权回调(包含code参数) if (isset($_GET['code'])) { // 检查授权错误 if (isset($_GET['error'])) { die('授权失败:' . htmlspecialchars($_GET['error'])); } // 构造令牌请求参数 $token_params = [ 'grant_type' => 'authorization_code', 'code' => $_GET['code'], 'redirect_uri' => $redirect_uri, 'code_verifier' => $_SESSION['code_verifier'] // 必须和授权请求时的code_verifier一致 ]; // 发送POST请求兑换令牌 $token_response = http($token_url, $token_params, [$auth_header]); // 检查令牌是否获取成功 if (!isset($token_response->access_token)) { die('获取访问令牌失败:' . (isset($token_response->error_description) ? $token_response->error_description : '未知错误')); } // 将用户ID存入Session,标识登录状态 $_SESSION['user_id'] = $token_response->user_id; // 可选:保存访问令牌和刷新令牌用于后续API请求 $_SESSION['access_token'] = $token_response->access_token; $_SESSION['refresh_token'] = $token_response->refresh_token; // 跳转到首页或用户页面 header('Location: /'); die(); } // 未登录状态,展示授权链接 $_SESSION['code_verifier'] = bin2hex(random_bytes(32)); // 生成安全的随机code_verifier $code_challenge = base64_urlencode(hash('sha256', $_SESSION['code_verifier'], true)); $authorize_url = 'https://www.fitbit.com/oauth2/authorize?' . http_build_query([ 'client_id' => $client_id, 'response_type' => 'code', 'code_challenge' => $code_challenge, 'code_challenge_method' => 'S256', 'scope' => 'activity heartrate location nutrition oxygen_saturation profile respiratory_rate settings sleep social temperature weight', 'redirect_uri' => $redirect_uri // 必须和令牌请求时的redirect_uri一致 ], null, '&', PHP_QUERY_RFC3986); echo '<p>未登录</p>'; echo '<p><a href="' . $authorize_url . '">登录Fitbit</a></p>'; // Base64 URL安全编码函数 function base64_urlencode($string) { return rtrim(strtr(base64_encode($string), '+/', '-_'), '='); } ?>
关键说明
- code_verifier生成:替换原固定字符串为随机生成的安全值,符合OAuth 2.0 PKCE规范
- 令牌请求参数:确保
redirect_uri与Fitbit开发者后台配置完全一致,code_verifier与授权请求时的对应值一致 - 登录状态标识:通过Session存储
user_id,后续页面可直接读取该值判断登录状态并展示 - 错误处理:新增令牌请求失败时的错误信息展示,便于调试
内容的提问来源于stack exchange,提问作者Gracie Smith
相关产品推荐
相关产品推荐

