使用python获取playstation奖杯数据 获取 token

微博   微信 10-12 14:50发布  江苏   45评论
exp
参考了 github 上通过 ps api 获取奖杯的方式,比较麻烦的部分是认证 token 的获取,github 项目关于这部分写的比较简单且使用的是 powershell 的方式。此处使用 python 重写了一遍,增加了 token 的刷新,部分 api 使用方式(翻译),文章底部会附上参考来源。

获取 token
1.1 获取 npsso
使用浏览器访问 playstation 官网登录账号(国服、港服都可以),之后在同一个浏览器(注意不要使用浏览器的无痕模式)中再访问 https://ca.account.sony.com/api/v1/ssocookie 获取 npsso。
1.2 获取 auth_code

import requests
from urllib.parse import parse_qs, urlparse

# 1.1 中获取的 npsso
npsso = "xrvW*****************************NYjq"
auth_url = "https://ca.account.sony.com/api/authz/v3/oauth/authorize"

# 固定参数
params = {
    "access_type": "offline",
    "client_id": "09515159-7237-4370-9b40-3806e67c0891",
    "response_type": "code",
    "scope": "psn:mobile.v2.core psn:clientapp",
    "redirect_uri": "com.scee.psxandroid.scecompcall://redirect",
}
auth_url += "?" + "&".join([f"{key}={value}" for key, value in params.items()])
response = requests.get(auth_url, cookies={"npsso": npsso}, allow_redirects=False)

# 请求的 status code 为 302,auth_code 在 response headers 中
if response.status_code == 302:
    location = response.headers.get("Location")
    query = parse_qs(urlparse(location).query)
    auth_code = query.get("code")[0]

1.3 获取 access_token 及 refresh_token

token_url = "https://ca.account.sony.com/api/authz/v3/oauth/token"

# 1.2 中获取的 auth_code
token_data = {
    "code": auth_code,
    "redirect_uri": "com.scee.psxandroid.scecompcall://redirect",
    "grant_type": "authorization_code",
    "token_format": "jwt",
}

# 请求头为固定内容
headers = {
    "Authorization": "Basic MDk1MTUxNTktNzIzNy00MzcwLTliNDAtMzgwNmU2N2MwODkxOnVjUGprYTV0bnRCMktxc1A=",
    "Content-Type": "application/x-www-form-urlencoded",
    "User-Agent": "PlayStation/21090100 CFNetwork/1126 Darwin/19.5.0",
}
response = requests.post(token_url, data=token_data, headers=headers)
response.raise_for_status()

# 请求成功后返回 access_token 及 refresh_token
access_token = response.json().get("access_token")
refresh_token = response.json().get("refresh_token")

access_token 时效只有 1 小时,refresh_token 的时效有 60 天,所以当 access_token 失效后,需要通过 refresh_token 来刷新 access_token。
1.4 刷新 access_token

token_url = "https://ca.account.sony.com/api/authz/v3/oauth/token"

# 1.1 中获取的 npsso
headers = {
    "Authorization": "Basic MDk1MTUxNTktNzIzNy00MzcwLTliNDAtMzgwNmU2N2MwODkxOnVjUGprYTV0bnRCMktxc1A=",
    "Cookie": f"npsso={npsso}",
    "User-Agent": "PlayStation/21090100 CFNetwork/1126 Darwin/19.5.0",
}

# 1.3 获取的 refresh_token
token_data = {
    "refresh_token": refresh_token,
    "scope": "psn:mobile.v2.core psn:clientapp",
    "grant_type": "refresh_token",
    "token_format": "jwt",
}
response = requests.post(token_url, data=token_data, headers=headers)
response.raise_for_status()

# 请求成功后获取 access_token
access_token = response.json().get("access_token")


评论
这个方式获取的奖杯数据信息,跟直接查用户有什么区别

P9好像是不用授权token就能查,授权查到的是跟PSApp里面一样吗?
incucc 10-12 17:42 广东
@incucc 如果有了token,可以查其他人或自己的数据。和psapp数据是一样的。api是从app中抓包拿到了。
zz-werke 10-13 14:33 江苏
如果有需要,日后可以直接使用psray项目的api
我们基于github上的一些psn-api项目,搭建一套公开的playstation api服务和网站,对于后续会对开发者免费提供
遗憾的是,现在没有时间来编写api文档,并且api会根据这边需求调整返回字段和请求参数,请不要用于正式的项目中

示例:例如需要获取个人资料,可以请求(请把最后替换成具体psnid)
https://api.psray.net/profile/get/abyssmoe
abyssmoe 10-14 12:16修改 日本
所以这个网站是看奖杯吗?还是干嘛的
coffeebean0421 10-14 10:39 广东
有这必要么
ssalor_1997 10-14 10:59 北京
正好前段时间也在搞自己的奖杯页,踩了点坑,用的是这个项目 https://psn-api.achievements.app/
npsso 以及获取到的 access_code 是有时效的,如果一直从这边走会要定期手动更新 npsso
但是用 refresh_token 去获取 access_token 时,在满足一定条件下会自己续 refresh_token 的剩余时间,来达到完全自动化,具体可以看这个 https://psn-api.achievements.app/api-docs/authentication#exchangerefreshtokenforauthtokens

目前自己的奖杯页初步已经完成,主要为了能够自定义别名,同时显示别名和原名,并且可以自定义展示的奖杯组且支持排序,这样我给别人展示我某个系列的奖杯就可以直接发一个地址
unclesev 10-14 14:06修改 上海
这个能获取游戏时长吗? 比如p9的在个人简介中输入特定字符,就可以获取,这种才方便
sephirothwkh 10-14 12:49 四川
@sephirothwkh 楼主列出的几个api接口不可以。可以获取,当要用别的接口。
abyssmoe 10-14 13:41 日本
扒数据最好就别明目张胆的发了
rookie926 10-14 13:59 辽宁
@rookie926 虽然索尼没有像steam那样公开数据接口,并且在这方面限制和管理比较模糊暧昧。但是开源社区的大家,还是研究了些方法获取数据,方便开发者们为玩家构建一些psn游戏相关的app或事网站服务。先不管是否用来盈利了,大家都希望为ps社区宣传,为本来就少的psn社区吸引更多的玩家。
扯远一点,说真的我感觉国内ps群体的新人越来越少,只剩下老登了。去年我搬家的时候送了朋友一台ps5,然后他至今都没怎么开机过。身边的人也大多在玩手机游戏和pc游戏。希望有能力的人,给PS玩家提供更好更方便的交流地方和功能,让更多人接触入坑ps,这是我们的理想。
abyssmoe 10-14 14:35 日本
上面的client_id和client_secret公开后,后来的人重新获取token,之前的不就失效了吗?
kongou233 10-14 15:02 江苏
获取auth_code时报错有大佬知道原因么?
{
"error": "invalid_request",
"error_code": 4098,
"error_description": "Mandatory parameter 'client_id' is missing"
}
skyfantasyhong 10-14 15:31 北京
@rookie926 这是索尼公开的api接口,公开api接口就是让大家进行合理调用的。和某些用Python无视规则扒数据还是有区别的,属于api的合法扩展应用
left_little_fox 10-14 15:55 广西
@kongou233 client_id目前看是固定的参数,多年没有更新了。
zz-werke 10-14 17:15 江苏
@abyssmoe 请教下,官方有获取游戏时长的借口吗?
zz-werke 10-14 17:17 江苏
@left_little_fox 应该也不是索尼公开的,目前看应该是从ps app应用中抓包拿到的。
zz-werke 10-14 17:20 江苏
@skyfantasyhong 1.1成功拿到npsso了吗,1.2中需要替换npsso变量。
zz-werke 10-14 17:24 江苏
@unclesev 使用refresh_token刷新access_token后也会返回refresh_token。文章只是简单写了下逻辑,具体代码需要自己构建。
zz-werke 10-14 17:34 江苏
@zz-werke 拿到npsso了,也加到header里了,但是一调就报错
skyfantasyhong 10-14 18:02 北京
@abyssmoe 惭愧了,几年前在黑盒搞过主机社区,但是因为老板觉得来钱慢就不想做了。索尼也不想搞基本盘,坐吃山空可太正常了。不如说大部分人都觉得可持续发展是个笑话,而且是全方位的只考虑眼前和自己了。
srvenx-07 10-15 13:37 河北
@skyfantasyhong 是不是少了参数,我今天测试也是没问题的。看报错像是少了client_id。
zz-werke 10-15 14:19 江苏
@zz-werke 但是参数都填了啊,是哪里的问题呢
skyfantasyhong 10-15 15:14 北京
@skyfantasyhong 起码参数得齐全了吧
params = {
"access_type": "offline",
"client_id": "09515159-7237-4370-9b40-3806e67c0891",
"response_type": "code",
"scope": "psn:mobile.v2.core psn:clientapp",
"redirect_uri": "com.scee.psxandroid.scecompcall://redirect",
}
nikezhang 10-15 16:07 北京
@srvenx-07 没,其实终究是在说漂亮话而已,现实就是费力回报少。作为独立开发者,开发的越久,越是迷茫还要不要坚持下去。要不是几位可爱的群友精神上的支持,我可能放弃了。

在这里谢谢他们。
abyssmoe 10-15 16:33修改 日本
@nikezhang 是写全了的,只不过截图挡住了
skyfantasyhong 10-15 16:40 北京
@skyfantasyhong 换postman试试,apifox可能会不好用
palmsprings_ 10-15 17:08 山东
@palmsprings_ 请教一下,cookies的值是npsso={获取到的npsso}的格式么?
skyfantasyhong 10-15 17:39 北京
@skyfantasyhong 当使用GET Method的时候,参数应该填写在query中。你的这张截图的请求头部对应的是http headers,query参数是http query。如果填写在请求体(body)中。不会有效的
abyssmoe 10-15 19:13修改 日本
@skyfantasyhong 你如果用apifox的,这个请求响应是302没有response
zz-werke 10-15 20:52修改 江苏
@palmsprings_ @abyssmoe @zz-werke 
用postman了,响应也是302了,但location里怎么感觉还是不对?求大佬赐教
skyfantasyhong 10-16 10:33 北京
@skyfantasyhong 参数顺序可能不对,cccess_type client_id redirect_uri respose_type scpoe 按照这个顺序试一下
palmsprings_ 10-16 11:38 山东
@palmsprings_ 换顺序了,还是不行唉
skyfantasyhong 10-16 11:59 北京
@skyfantasyhong 和参数顺序没关系,在postman中是能正常拿到location的,settings中有个配置Automatically follow redirects自动重定向,需要关了,默认是打开的。
zz-werke 10-16 15:20修改 江苏
@zz-werke Automatically follow redirects我关了,不关都不是302而是200,现在问题就是结果拿到location了但里面的内容不对
skyfantasyhong 10-16 15:22 北京
@zz-werke 我的location里不是com.scee开头的,而是https://my.account.sony.com/sonyacct/signin开头的,不知道问题在哪
skyfantasyhong 10-16 15:24 北京
@skyfantasyhong headers中加cookie了吗
zz-werke 10-16 15:41 江苏
@zz-werke 加cookie了,还是不行,headers我是6个hidden你是8个,跟这个有关系么?
skyfantasyhong 10-16 16:02 北京
@skyfantasyhong 其他参数是postman默认的
zz-werke 10-16 16:50 江苏
@zz-werke 完全按照这个试了还是不行,无解了
skyfantasyhong 10-16 17:45 北京
@skyfantasyhong 你看看你的帐号的隐私设置吧,那一大堆返回值里有个error_code和error_description,写的是用户没有授权,应该和你的隐私设置有关系,要不就是需要登录。
另外你是直接用的人家的client_id?那肯定是不行的,你得用你自己的才行,而且,他这种方式是要你浏览器登录之后获取自己账号相关的cookie才行的,你带的cookie对吗?还得和自己的client_id匹配。
nikezhang 10-22 00:47修改 北京
@nikezhang 但是不知道什么隐私会影响这个接口呢,client_id是固定值所有人都是用一样的啊,就是npsso应该用自己的,而我也确实用了自己的啊
skyfantasyhong 10-22 17:27 北京


请求这个api可以拿到每个游戏的游玩时长,游戏多可以加limit和offset参数
https://m.np.playstation.com/api/gamelist/v2/users/me/titles?categories=ps4_game,ps5_native_game
e-rubecula 10-24 15:05 上海
@skyfantasyhong 那个client_id是app的id吧,我理解成用户自己的id了,那个应该是一样的,不过错误信息里既然是提示需要登录,那应该就是和某些配置冲突了。
nikezhang 10-30 16:59 北京
@skyfantasyhong 刚才我用python试了下,没有带上cookie返回的location里就会是这样显示的,你检查下你用的工具是否正确的带上了cookie吧
nikezhang 10-30 18:52 北京
我也遇到code获取不了的情况报错这个:
[error] => login reguired
[error _code]=> 4165
[error description]=>User is not authenticated
no captcha] => true
@skyfantasyhong 您那边问题解决了吗?
有没有大佬指点这个怎么解决呀?
arcangelostation 8天前 14:52 北京
回复不能
T