首页> 实战笔录 >PHP开发笔记 >Hyperf Hyperf

hyperf3.1实现apple第三方网页授权登录

作者:小萝卜 2025-04-04 浏览 89

简介完整流程: 1.点击前端 Apple 登录按钮。2.用户授权后,Hyperf 会收到包含 code 的 POST 请求。3.后端通过 code 换取 access_token 并获取用户数据。4.返回用户信息或执行登录逻辑。

一、准备工作(具体请参考:Apple第三方网页授权登录-OAuth客户端创建配置流程

  1. 注册 Apple 开发者账号

    • 前往 Apple Developer 创建应用 ID

    • 启用 "Sign In with Apple" 功能

  2. 获取必要参数

    • Service ID (客户端ID):如 com.example.service

    • Team ID:开发者团队ID

    • 密钥文件 (.p8):用于生成客户端密钥

    • Key ID:生成密钥时获得的标识
       

1. 安装依赖

 
composer require league/oauth2-client
composer require patrickbussmann/oauth2-apple


2. 配置参数

在 config/autoload/oauth.php 中配置 Apple 参数:

<?php
return [
    'apple' => [
        'client_id' => env('APPLE_CLIENT_ID'),       // Service ID (如 com.company.service)
        'team_id' => env('APPLE_TEAM_ID'),          // 开发者账号 Team ID
        'key_id' => env('APPLE_KEY_ID'),            // 私钥 Key ID
        'redirect_uri' => env('APPLE_REDIRECT_URI'),// 回调地址
        'key_path' => BASE_PATH . '/storage/apple/AuthKey.p8', // .p8 私钥文件路径
    ],
];


3. 创建控制器

 
declare(strict_types=1);

namespace App\Http\Api\Controller\V1;

use App\Http\Api\Controller\Common\BaseController;
use App\Http\Common\MineFormRequest;
use App\Repository\member\TMemberRepository;
use App\Service\crm\MemberThirdAuthService;
use Hyperf\Collection\Arr;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\Redis\Redis;
use League\OAuth2\Client\Provider\Google;

#[Controller(prefix: 'third/login')]
class MemberThirdAuthController extends BaseController
{
    #[Inject]
    public Redis $redis;

    #[Inject]
    public MemberThirdAuthService $service;

    /**
     * @param ResponseInterface $response
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Exception
     * @description  apple跳转授权登录
     * @author: Luobo
     * @date: 2025/3/6 19:49
     */
    #[GetMapping("apple")]
    public function appleLogin(ResponseInterface $response)
    {

        $state = bin2hex(random_bytes(16)); // 防 CSRF
        // 存储 state 到 redis 或缓存
        $this->redis->set('oauth:apple:state:' . $state, 'valid', 300);

        $provider = $this->service->getProvider();
        $authUrl = $provider->getAuthorizationUrl([
            'scope' => 'name email', // 请求用户姓名和邮箱
            'state' => $state,
        ]);

        return $response->redirect($authUrl);
    }

    /**
     * @param MineFormRequest $request
     * @param ResponseInterface $response
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @description  apple跳转授权回调地址
     * @author:Luobo
     * @date: 2025/3/7 10:30
     */
    #[PostMapping("apple_callback")]
    public function appleCallback(MineFormRequest $request,ResponseInterface $response)
    {
        $provider = $this->service->getProvider();
        $code = $request->input('code');
        $state = $request->input('state');

        // 验证 state(需从 Session/Cache 中比对)
        if (!$this->redis->exists('oauth:apple:state:' . $state)) {
            throw new \RuntimeException(crmTrans('Invalid state'));
        }

        try {
            $token = $provider->getAccessToken('authorization_code', ['code' => $code]);
            $appleUser = $provider->getResourceOwner($token);

            // 处理用户信息
            $sub = $appleUser->getId();
            $email = $appleUser->getEmail();
            $name = $appleUser->getFirstName() . ' ' . $appleUser->getLastName();

            $url = $this->service->setWebUser(['sub'=>$sub,'email'=>$email,'name'=>$name,'picture'=>'','plateform'=>'Apple'],$request);

            return $response->redirect($url);

        } catch (\Exception $e) {
            return $response->json(['error' => $e->getMessage()], 400);
        }
    }

}

很赞哦! (0)

文章评论

    高端网站建设