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

Philips TV APIv6配对异常:/pair/grant请求返回HTTP 200 OK但JSON响应提示"INVALID_PIN"(自定义Android应用与Python脚本均复现)

Philips TV APIv6配对异常:/pair/grant请求返回HTTP 200 OK但JSON响应提示"INVALID_PIN"(自定义Android应用与Python脚本均复现)

我现在在给飞利浦43PUS8309/62型号的电视(基于安卓/Linux系统,API版本6)开发配对功能,分别用了Android(Java/Kotlin+OkHttp)和Python两种实现,但卡在了同一个地方,想请教大家有没有解决思路。

先给大家理一下我按照资料(包括网上的文档和一个Python参考脚本)实现的配对流程:

配对步骤

  1. 请求配对初始化
    向/6/pair/request发送POST请求,Payload是:

    {
      "scope": ["read", "write", "control"],
      "device": {
        "device_name": "...",
        "device_os": "...",
        "app_id": "...",
        "app_name": "...",
        "type": "native",
        "id": "CLIENT_GENERATED_ID"
      }
    }
    

    TV返回200 OK,JSON里包含auth_key和timestamp,同时电视屏幕上会弹出PIN码。

  2. 用户输入PIN后提交授权
    向/6/pair/grant发送POST请求,这个请求有两个关键要求:

    • HTTP摘要认证:用户名是步骤1里的CLIENT_GENERATED_ID,密码是步骤1返回的auth_key
    • JSON Payload:
      {
        "auth": {
          "pin": "USER_ENTERED_PIN",
          "auth_timestamp": TIMESTAMP_FROM_STEP_1, // 以数字类型发送
          "auth_signature": "CALCULATED_HMAC_SIGNATURE",
          "auth_AppId": 1 // 数字类型
        },
        "device": { /* 和步骤1里完全一样的device对象 */ }
      }
      

    其中auth_signature的计算逻辑是:
    Base64.encode(UTF8_bytes( HexString( HMAC_SHA1(decoded_secret_key, UTF8_bytes(timestamp_string + pin_string)) ) ))
    这里的secret_key是一个固定的Base64字符串,我已经正确解码后用于计算。

遇到的问题

不管是Android应用还是Python脚本,都出现了同一个问题:

  • 步骤1完全正常,能拿到auth_key和timestamp,电视也弹出了PIN
  • 第一次发/pair/grant的时候因为没加摘要头,返回401 Unauthorized,这符合预期
  • 第二次带上正确计算的摘要认证头再发/pair/grant,返回了200 OK,但JSON响应体却是:
    {"error_id": "INVALID_PIN", "error_text": "Invalid authentication parameters"}
    
    也就是说,摘要认证过了,但PIN相关的参数被判定为无效,可我明明输入了电视上显示的正确PIN啊!

我已经排查验证过的点

为了定位问题,我已经逐一验证了这些内容:

  • HTTP摘要认证是有效的:返回200 OK说明电视已经接受了摘要凭证,排除了认证本身的问题
  • HMAC签名计算正确:我用相同的timestamp、pin和secret_key分别在Java和Python里计算,得到的auth_signature完全一致(比如用timestamp="2527"、pin="8763",两者算出的Base64字符串都是ZTkwMWE4MTQyNDhmMzdkZDAzNWRjMjY1YzFmM2VlZWViM2JlYTgyNA==)
  • JSON Payload格式完全正确:
    • auth_timestamp是以数字类型发送的(Java用Long,Python用int)
    • auth_AppId也是数字类型的1
    • device对象和步骤1里完全一致,包括id是同一个客户端生成的ID
  • 模仿官方应用参数:我抓了官方飞利浦电视遥控器APP的日志,把它的device_name、app_name、app_id都抄到我的Payload里,结果还是一样的INVALID_PIN
  • 增加前置请求:按照官方APP的流程,在配对前先给http://<TV_IP>:1925/system发了一个未认证的GET请求,之后再走1926端口的配对流程,问题依然存在

附上我的Python脚本关键片段

from __future__ import print_function, unicode_literals
from base64 import b64encode, b64decode
import json
import requests
import random
import string
from Crypto.Hash import SHA, HMAC  # 用于HMAC-SHA1计算
from requests.auth import HTTPDigestAuth
import sys

# 固定的Secret Key(Base64格式),解码后用于HMAC计算
SECRET_KEY_BASE64 = "ZmVay1EQVFOaZhwQ4Kv81ypLAZNczV9sG4KkseXWn1NEk6cXmPKO/MCa9sryslvLCFMnNe4Z4CPXzToowvhHvA=="
DECODED_SECRET_KEY_BYTES = b64decode(SECRET_KEY_BASE64)

def create_device_id():
    # 生成随机的客户端ID
    return ''.join(random.choices(string.ascii_uppercase + string.digits, k=16))

# 步骤1:请求配对初始化
def request_pairing(tv_ip, device_info):
    url = f"https://{tv_ip}:1926/6/pair/request"
    payload = {
        "scope": ["read", "write", "control"],
        "device": device_info
    }
    # 测试环境暂时禁用SSL警告
    requests.packages.urllib3.disable_warnings()
    response = requests.post(url, json=payload, verify=False)
    if response.status_code == 200:
        return response.json()
    else:
        print(f"请求配对初始化失败:{response.status_code}")
        return None

# 计算HMAC签名
def calculate_auth_signature(timestamp, pin):
    message = f"{timestamp}{pin}".encode('utf-8')
    hmac = HMAC.new(DECODED_SECRET_KEY_BYTES, message, SHA)
    hex_digest = hmac.hexdigest()
    # 转成UTF-8字节再Base64编码
    return b64encode(hex_digest.encode('utf-8')).decode('utf-8')

# 步骤2:提交PIN和授权
def grant_pairing(tv_ip, device_info, client_id, auth_key, timestamp, pin):
    url = f"https://{tv_ip}:1926/6/pair/grant"
    auth_signature = calculate_auth_signature(str(timestamp), pin)
    payload = {
        "auth": {
            "pin": pin,
            "auth_timestamp": int(timestamp),
            "auth_signature": auth_signature,
            "auth_AppId": 1
        },
        "device": device_info
    }
    # 构建摘要认证
    digest_auth = HTTPDigestAuth(client_id, auth_key)
    requests.packages.urllib3.disable_warnings()
    response = requests.post(url, json=payload, auth=digest_auth, verify=False)
    print(f"授权请求状态码:{response.status_code}")
    print(f"授权响应内容:{response.text}")
    return response.json()

# 主流程示例
if __name__ == "__main__":
    TV_IP = "192.168.1.100"  # 替换成你的电视IP
    client_id = create_device_id()
    device_info = {
        "device_name": "MyTestDevice",
        "device_os": "Android 13",
        "app_id": "com.my.test.app",
        "app_name": "TestTVRemote",
        "type": "native",
        "id": client_id
    }
    # 步骤1
    pairing_resp = request_pairing(TV_IP, device_info)
    if not pairing_resp:
        sys.exit(1)
    auth_key = pairing_resp['auth_key']
    timestamp = pairing_resp['timestamp']
    print(f"拿到auth_key: {auth_key}, timestamp: {timestamp}")
    # 等待用户输入PIN
    pin = input("请输入电视上显示的PIN码:")
    # 步骤2
    grant_resp = grant_pairing(TV_IP, device_info, client_id, auth_key, timestamp, pin)

我已经卡了好几天了,所有能想到的点都查过了,还是不知道为什么会提示PIN无效,有没有做过同款电视配对的朋友遇到过类似问题?或者有没有我漏掉的细节没考虑到?


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 11:15:28