You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:31:08