接入google play token 校验

This commit is contained in:
liyunjia 2025-01-05 21:25:07 +08:00
parent a99589283a
commit c51f80b2f3

View File

@ -45,6 +45,10 @@ pub struct GoogleJwtProfile {
pub given_name: String,
pub family_name: String,
pub locale: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub google_play_games_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub google_play_games_profile: Option<String>,
}
impl GoogleJwtProfile {
@ -159,4 +163,76 @@ impl GoogleSocial {
Ok(google_jwt_profile)
}
/// 验证 Google Play Games 的身份信息
/// 参考: https://developers.google.com/games/services/android/signin
pub async fn verify_play_games_token(&self, play_games_token: &str) -> SocialResult<GoogleJwtProfile> {
// Google Play Games 的验证端点
const GOOGLE_PLAY_GAMES_TOKEN_INFO_URL: &str =
"https://oauth2.googleapis.com/tokeninfo";
let client = Client::new();
let response = client
.get(GOOGLE_PLAY_GAMES_TOKEN_INFO_URL)
.query(&[("access_token", play_games_token)])
.send()
.await?;
if !response.status().is_success() {
return Err(Box::new(ResErr::social("验证 Google Play Games Token 失败")));
}
let token_info: Value = response.json().await?;
// 验证 token 信息
if let Some(error) = token_info.get("error") {
return Err(Box::new(ResErr::social(format!(
"Google Play Games Token 无效: {}",
error
))));
}
// 验证 audience 是否匹配你的应用
if let Some(aud) = token_info.get("aud") {
// TODO: 验证 aud 是否匹配你的 Google Play Games 应用 ID
tracing::debug!("Google Play Games aud: {}", aud);
}
// 构建用户资料
let mut profile = GoogleJwtProfile::default();
if let Some(sub) = token_info.get("sub").and_then(|v| v.as_str()) {
profile.sub = sub.to_string();
}
if let Some(email) = token_info.get("email").and_then(|v| v.as_str()) {
profile.email = email.to_string();
}
// 获取 Google Play Games 特定的信息
let play_games_info = self.fetch_play_games_profile(play_games_token).await?;
profile.google_play_games_id = play_games_info.get("playerId")
.and_then(|v| v.as_str())
.map(String::from);
Ok(profile)
}
/// 获取 Google Play Games 用户资料
async fn fetch_play_games_profile(&self, access_token: &str) -> SocialResult<Value> {
const PLAY_GAMES_PROFILE_URL: &str =
"https://games.googleapis.com/games/v1/players/me";
let client = Client::new();
let response = client
.get(PLAY_GAMES_PROFILE_URL)
.header("Authorization", format!("Bearer {}", access_token))
.send()
.await?;
if !response.status().is_success() {
return Err(Box::new(ResErr::social("获取 Google Play Games 用户资料失败")));
}
let profile: Value = response.json().await?;
Ok(profile)
}
}