在 WWDC2019 中,苹果官方约定如果新的APP(目前为止未在AppStore发布过的), 如果有第三方登录功能(QQ登录,谷歌登录等等), 那么必须适配苹果推出的Sign In With Apple才能被审核通过。
2.1 具体配置 参考 :https://mp.weixin.qq.com/s/xkxCnKqA0u-guEYcYCkcOg 或者谷歌
client_id 为 配置中的 Bundle ID 通常为 com.xxx.xxx
client_secret 后端需要根据 client_id / team_id / key_id / p8文件 这几个参数 生成
生成 client_secret 需要使用下面这个 ruby
脚本 创建 secret_gen.rb
文件并将下面代码复制进去
require "jwt"
key_file = "P8文件本地路径"
team_id = "Your Team ID"
client_id = "Your App Bundle ID"
key_id = "The Key ID of the private key"
validity_period = 180 # In days. Max 180 (6 months) according to Apple docs.
private_key = OpenSSL::PKey::EC.new IO.read key_file
token = JWT.encode(
{
iss: team_id,
iat: Time.now.to_i,
exp: Time.now.to_i + 86400 * validity_period,
aud: "https://appleid.apple.com",
sub: client_id
},
private_key,
"ES256",
header_fields=
{
kid: key_id
}
)
puts token
修改这四个参数
key_file = "P8文件本地路径"
team_id = "Your Team ID"
client_id = "Your App Bundle ID"
key_id = "The Key ID of the private key"
运行 ruby secret_gen.rb 就可以生成 client_secret 了(本地需要有 ruby 环境)
composer require laravel/socialite
composer require socialiteproviders/apple
在 config/services.php
文件中 中增加配置项
'apple' => [
'client_id' => env('APPLE_CLIENT_ID'), // client id
'client_secret' => env('APPLE_CLIENT_SECRET'), // 生成好的 client_secret
'redirect' => env('APPLE_REDIRECT_URI') // APP端不需要这个 为空或者随便写入一个地址 如: `https://example-app.com/redirect`
]
在 app/Providers/EventServiceProvider
文件中的 listen[]
数组中增加
protected $listen = [
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
// ... other providers
'SocialiteProviders\\Apple\\AppleExtendSocialite@handle',
],
];
需要在用户表增加 apple openid 字段 apple openid 字段格式为 000472.39a0b935d1f14d2bae90c8d68abd1c3b.0450
可以增加一个 apple openid_hash字段 用来建立索引查询 hash字段的值为 md5(openid)
如果没有用 openid_hash 字段给 openid 字段增加唯一索引
如果使用 openid_hash 字段给 openid_hash 字段增加唯一索引 openid字段不需要索引了
假设在 业务代码在 LoginController
的loginByApple
方法中
code : [必须的参数] code参数即是APP端获取的 authorizationCode 参数,authorizationCode 原始格式为二进制需要转为普通的字符串传递给后端
用户信息参数: 用户第一次登录的时候APP端可以获取到 用户的邮箱 和 用户名 (邮箱如果用户不给权限 Apple会给一个中转邮箱)
可以根据业务是否需要这两个字段 只有第一次登录会有这两个参数 所以这两个参数不是必须的
其它参数: 根据业务自行设计
public function loginByApple()
{
try{
/* @var \SocialiteProviders\Manager\OAuth2\User $user*/
if ($oauthUser = \Laravel\Socialite\Facades\Socialite::with('apple')->stateless()->user()) {
// 0. 进入这里 说明登录成功 继续获取 openid, openid 是用户的唯一标示
// 1. 获取open id
$openId = $oauthUser->getId();
// 2. 根据open id (或者 open id hash)查找用户是否存在
// 3. 存在的处理
// 4. 不存在创建用户处理
// 5. 其它更多具体业务的处理
}
}catch(\Throwable $t){
// 这里错误有常见两种
// 1. Client error: POST https://appleid.apple.com/auth/token resulted in a 400 Bad Request response:\n{\"error\":\"invalid_client\"}\n
// 提示 invalid_client 的错误 说明配置 client_id 或者 client_secret 错误 通常是 client_secret 错误 请检查配置项和生成脚本
// 2. 提示 grant 错误 很可能因为客户端提交的 code 参数被使用了
}
}