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

如何通过Python/PSN API获取PlayStation Network的SSO Cookie?

修复GOG Galaxy的PlayStation Network插件:获取PSN SSO Token/Cookie方案

问题背景

非程序员用户求助修复GOG Galaxy的PSN插件:插件原本通过弹窗登录同步游戏库,之前靠替换代码从指定链接获取npsso Cookie恢复功能,但现在该链接返回HTTP 429错误失效。尝试过的第三方Python库仍需SSO Token,无法解决问题,现寻求获取PSN SSO Token/Cookie的有效方法。

插件代码:

import logging
import sys
from typing import List, Any, AsyncGenerator

from galaxy.api.consts import Platform, LicenseType
from galaxy.api.errors import InvalidCredentials
from galaxy.api.plugin import Plugin, create_and_run_plugin
from galaxy.api.types import Authentication, Game, NextStep, SubscriptionGame, \
    Subscription, LicenseInfo

from http_client import HttpClient
from http_client import OAUTH_LOGIN_URL, OAUTH_LOGIN_REDIRECT_URL
from psn_client import PSNClient

from version import __version__

AUTH_PARAMS = {
    "window_title": "Login to My PlayStation\u2122",
    "window_width": 536,
    "window_height": 675,
    "start_uri": OAUTH_LOGIN_URL,
    "end_uri_regex": "^" + OAUTH_LOGIN_REDIRECT_URL + ".*"
}


logger = logging.getLogger(__name__)


class PSNPlugin(Plugin):
    def __init__(self, reader, writer, token):
        super().__init__(
            Platform.Psn, __version__, reader, writer, token)
        self._http_client = HttpClient()
        self._psn_client = PSNClient(self._http_client)
        logging.getLogger("urllib3").setLevel(logging.FATAL)

    async def _do_auth(self, cookies):
        if not cookies:
            raise InvalidCredentials()

        self._http_client.set_cookies_updated_callback(self._update_stored_cookies)
        self._http_client.update_cookies(cookies)
        await self._http_client.refresh_cookies()
        user_id, user_name = await self._psn_client.async_get_own_user_info()
        if user_id == "":
            raise InvalidCredentials()
        return Authentication(user_id=user_id, user_name=user_name)

    async def authenticate(self, stored_credentials=None):
        stored_cookies = stored_credentials.get("cookies") if stored_credentials else None
        if not stored_cookies:
            return NextStep("web_session", AUTH_PARAMS)

        auth_info = await self._do_auth(stored_cookies)
        return auth_info

    async def pass_login_credentials(self, step, credentials, cookies):
        cookies = {cookie["name"]: cookie["value"] for cookie in cookies}
        self._store_cookies(cookies)
        return await self._do_auth(cookies)

    def _store_cookies(self, cookies):
        credentials = {
            "cookies": cookies
        }
        self.store_credentials(credentials)

    def _update_stored_cookies(self, morsels):
        cookies = {}
        for morsel in morsels:
            cookies[morsel.key] = morsel.value
        self._store_cookies(cookies)

    async def get_subscriptions(self) -> List[Subscription]:
        is_plus_active = await self._psn_client.get_psplus_status()
        return [Subscription(subscription_name="PlayStation PLUS", end_time=None, owned=is_plus_active)]

    async def get_subscription_games(self, subscription_name: str, context: Any) -> AsyncGenerator[List[SubscriptionGame], None]:
        yield await self._psn_client.get_subscription_games()

    async def get_owned_games(self):
        def game_parser(title):
            return Game(
                game_id=title["titleId"],
                game_title=title["name"],
                dlcs=[],
                license_info=LicenseInfo(LicenseType.SinglePurchase, None)
            )

        def parse_played_games(titles):
            return [{"titleId": title["titleId"], "name": title["name"]} for title in titles]

        purchased_games = await self._psn_client.async_get_purchased_games()
        played_games = parse_played_games(await self._psn_client.async_get_played_games())
        unique_all_games = {game['titleId']: game for game in played_games + purchased_games}.values()
        return [game_parser(game) for game in unique_all_games]

    async def shutdown(self):
        await self._http_client.close()


def main():
    create_and_run_plugin(PSNPlugin, sys.argv)


if __name__ == "__main__":
    main()

有效解决方案

  1. 用浏览器正常登录PlayStation官网,保持登录状态
  2. 打开浏览器开发者工具(F12或Ctrl+Shift+I)
  3. 切换到「应用程序」标签,展开「Cookie」,选择account.sony.com域名
  4. 在Cookie列表中找到npsso,复制其对应的值

提取后,可按之前的方法替换插件代码中的对应部分,或修改插件添加手动输入npsso的功能。此方法不会触发429错误,因为是从已建立的登录会话中提取,而非直接请求API链接。

恢复原生登录流程

原生弹窗登录失效可能因索尼更新OAuth端点:

  • 检查插件依赖的http_client.py文件中,OAUTH_LOGIN_URL和OAUTH_LOGIN_REDIRECT_URL是否为当前有效的索尼登录地址
  • 若地址过期,替换为索尼最新的OAuth登录端点(可参考活跃PSN第三方工具的配置)

适配第三方PSN库的认证逻辑

针对提到的第三方Python库,可整合其认证流程到插件中:

  1. 修改插件的authenticate方法,支持手动输入npsso值来获取后续认证Token
  2. 将库中的认证代码替换插件原有的Cookie认证逻辑,实现自动从npsso生成有效会话

注意事项

  • npsso值有有效期,过期后需重新提取
  • 切勿分享npsso,它等同于PSN账号凭证
  • 修改插件前备份原文件,避免操作失误导致插件彻底无法使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:24:55