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

如何在PHP及Laravel框架中使用Google Fit API同步应用数据?

在Laravel中集成Google Fit API同步数据

1. 配置Google Cloud项目

  • 登录Google Cloud Console,创建新项目
  • 搜索并启用Google Fit API
  • 进入「API和服务」→「凭据」,创建「OAuth 2.0 客户端ID」
  • 应用类型选择「Web应用」,添加授权回调地址(示例:https://your-domain.com/google-fit/callback)
  • 记录生成的客户端ID、客户端密钥

2. 安装依赖

在Laravel项目根目录执行Composer命令:

composer require google/apiclient

3. 配置环境变量

在.env文件中添加以下配置:

GOOGLE_CLIENT_ID=你的客户端ID
GOOGLE_CLIENT_SECRET=你的客户端密钥
GOOGLE_FIT_REDIRECT_URI=https://your-domain.com/google-fit/callback

4. 定义路由

在routes/web.php中添加:

Route::get('/google-fit/auth', [App\Http\Controllers\GoogleFitController::class, 'auth']);
Route::get('/google-fit/callback', [App\Http\Controllers\GoogleFitController::class, 'callback']);

5. 创建控制器

生成GoogleFitController:

php artisan make:controller GoogleFitController

在控制器中实现授权、回调及数据同步逻辑:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Google\Client;
use Google\Service\Fitness;

class GoogleFitController extends Controller
{
    protected $client;

    public function __construct()
    {
        $this->client = new Client();
        $this->client->setClientId(env('GOOGLE_CLIENT_ID'));
        $this->client->setClientSecret(env('GOOGLE_CLIENT_SECRET'));
        $this->client->setRedirectUri(env('GOOGLE_FIT_REDIRECT_URI'));
        // 根据需求添加权限范围
        $this->client->addScope([
            'https://www.googleapis.com/auth/fitness.activity.read',
            'https://www.googleapis.com/auth/fitness.body.read'
        ]);
        $this->client->setAccessType('offline'); // 获取refresh_token用于令牌刷新
    }

    // 跳转至Google授权页面
    public function auth()
    {
        $authUrl = $this->client->createAuthUrl();
        return redirect($authUrl);
    }

    // 授权回调处理
    public function callback(Request $request)
    {
        $token = $this->client->fetchAccessTokenWithAuthCode($request->code);
        
        // 保存令牌到用户表(需提前为users表添加google_fit_access_token、google_fit_refresh_token、google_fit_expires_at字段)
        auth()->user()->update([
            'google_fit_access_token' => $token['access_token'],
            'google_fit_refresh_token' => $token['refresh_token'],
            'google_fit_expires_at' => now()->addSeconds($token['expires_in'])
        ]);

        return redirect('/dashboard')->with('success', 'Google Fit授权成功');
    }

    // 同步用户Fit数据(以步数为例)
    public function syncData()
    {
        $user = auth()->user();
        
        // 检查令牌是否过期,过期则自动刷新
        if (now()->gte($user->google_fit_expires_at)) {
            $this->client->setRefreshToken($user->google_fit_refresh_token);
            $newToken = $this->client->fetchAccessTokenWithRefreshToken();
            
            $user->update([
                'google_fit_access_token' => $newToken['access_token'],
                'google_fit_expires_at' => now()->addSeconds($newToken['expires_in'])
            ]);
            $this->client->setAccessToken($newToken['access_token']);
        } else {
            $this->client->setAccessToken($user->google_fit_access_token);
        }

        $fitService = new Fitness($this->client);

        // 定义数据请求参数:最近7天的步数,按天聚合
        $startTime = strtotime('-7 days') * 1000000000; // 转换为纳秒时间戳
        $endTime = time() * 1000000000;

        $requestBody = new Fitness\AggregateRequest([
            'aggregateBy' => [
                new Fitness\AggregateBy([
                    'dataTypeName' => 'com.google.step_count.delta',
                    'dataSourceId' => 'derived:com.google.step_count.delta:com.google.android.gms:estimated_steps'
                ])
            ],
            'bucketByTime' => new Fitness\BucketByTime(['durationMillis' => 86400000]), // 按天分组
            'startTimeMillis' => $startTime,
            'endTimeMillis' => $endTime
        ]);

        // 调用API获取数据
        $response = $fitService->users_dataset->aggregate('me', $requestBody);

        // 处理返回数据并保存到本地数据库(需提前创建fit_steps表,包含user_id、date、steps字段)
        foreach ($response->getBucket() as $bucket) {
            foreach ($bucket->getDataset() as $dataset) {
                foreach ($dataset->getPoint() as $point) {
                    $steps = $point->getValue()[0]->getIntVal();
                    $date = date('Y-m-d', $bucket->getStartTimeMillis() / 1000);
                    
                    \App\Models\FitStep::updateOrCreate(
                        ['user_id' => $user->id, 'date' => $date],
                        ['steps' => $steps]
                    );
                }
            }
        }

        return response()->json(['message' => '数据同步成功']);
    }
}

6. (可选)定时自动同步

  • 创建同步命令:
php artisan make:command SyncGoogleFitData

在app/Console/Commands/SyncGoogleFitData.php中编写批量同步逻辑:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Http\Controllers\GoogleFitController;

class SyncGoogleFitData extends Command
{
    protected $signature = 'fit:sync';
    protected $description = '同步所有已授权用户的Google Fit数据';

    public function handle()
    {
        $controller = new GoogleFitController();
        // 遍历所有已授权Google Fit的用户
        $users = \App\Models\User::whereNotNull('google_fit_refresh_token')->get();
        
        foreach ($users as $user) {
            auth()->login($user);
            $controller->syncData();
        }

        $this->info('Google Fit数据同步完成');
    }
}
  • 在app/Console/Kernel.php中添加调度规则:
protected function schedule(Schedule $schedule)
{
    $schedule->command('fit:sync')->daily(); // 每天自动同步一次
}

注意事项

  • 权限范围根据实际业务需求调整,如需写入数据可添加fitness.activity.write等权限
  • 需处理API调用异常(如网络错误、权限不足),避免同步流程中断
  • 令牌刷新逻辑需保证稳定性,防止因令牌过期导致同步失败

内容的提问来源于stack exchange,提问作者developer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 19:35:22