{"record":{"id":"9edb8659ba08e6fd","repo":"fish2018/pansou","slug":"ptsigx","errorCode":null,"errorMessage":"未找到ptsigx","messagePattern":"未找到ptsigx","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/qqpd/qqpd.go","lineNumber":1857,"sourceCode":"\tstart := strings.Index(responseText, \"ptuiCB(\")\n\tif start == -1 {\n\t\treturn \"\", \"\", fmt.Errorf(\"未找到ptuiCB\")\n\t}\n\n\t// 简单解析，提取URL部分\n\tre := regexp.MustCompile(`ptuiCB\\('0','0','([^']+)'`)\n\tmatches := re.FindStringSubmatch(responseText)\n\tif len(matches) < 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"无法解析响应\")\n\t}\n\n\turl := matches[1]\n\n\t// 提取ptsigx\n\tptsigxRe := regexp.MustCompile(`ptsigx=([A-Za-z0-9]+)`)\n\tptsigxMatches := ptsigxRe.FindStringSubmatch(url)\n\tif len(ptsigxMatches) < 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"未找到ptsigx\")\n\t}\n\tptsigx := ptsigxMatches[1]\n\n\t// 提取uin\n\tuinRe := regexp.MustCompile(`uin=(\\d+)`)\n\tuinMatches := uinRe.FindStringSubmatch(url)\n\tif len(uinMatches) < 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"未找到uin\")\n\t}\n\tuin := uinMatches[1]\n\n\treturn ptsigx, uin, nil\n}\n\n// fetchFullCookie 获取完整Cookie\nfunc (p *QQPDPlugin) fetchFullCookie(uin, ptsigx, setCookieHeader string) (string, error) {\n\tcheckSigURL := fmt.Sprintf(\"https://ptlogin2.pd.qq.com/check_sig?pttype=1&uin=%s&service=ptqrlogin&nodirect=1&ptsigx=%s&s_url=https%%3A%%2F%%2Fpd.qq.com%%2Fexplore&f_url=&ptlang=2052&ptredirect=101&aid=1600001587&daid=823&j_later=0&low_login_hour=0&regmaster=0&pt_login_type=3&pt_aid=0&pt_aaid=16&pt_light=0&pt_3rd_aid=0\", uin, ptsigx)\n","sourceCodeStart":1839,"sourceCodeEnd":1875,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/qqpd/qqpd.go#L1839-L1875","documentation":"extractLoginInfo (plugin/qqpd/qqpd.go:1857) matched the ptuiCB callback and URL, but the regex `ptsigx=([A-Za-z0-9]+)` found no ptsigx parameter in the extracted URL, so it returns '未找到ptsigx'. ptsigx is the signing token required for the follow-up check_sig cookie exchange, so login cannot proceed without it.","triggerScenarios":"checkQRLoginStatus -> extractLoginInfo: the ptuiCB URL exists but lacks a ptsigx query parameter — QQ returned a redirect URL variant without the sign token.","commonSituations":"QQ A/B-testing a new login URL shape, the URL being a jump/verify URL (e.g. needing an extra verification step), or a truncated/malformed callback URL.","solutions":["Log the extracted URL and inspect which query parameters are actually present","Update the ptsigx regex if QQ changed the parameter name or charset (e.g. allowing '_' or '%')","Handle alternate URL forms (URL-decode first in case the sign param is percent-encoded)","Regenerate the QR code and retry the login flow"],"exampleFix":"// before\nptsigxRe := regexp.MustCompile(`ptsigx=([A-Za-z0-9]+)`)\n// after\nptsigxRe := regexp.MustCompile(`ptsigx=([^&']+)`)","handlingStrategy":"validation","validationCode":"// verify expected query params before extraction\nu, err := url.Parse(extractedURL)\nif err != nil {\n    return fmt.Errorf(\"bad login url: %w\", err)\n}\nif u.Query().Get(\"ptsigx\") == \"\" {\n    return errors.New(\"login url missing ptsigx\")\n}","typeGuard":"func hasPtsigx(loginURL string) bool {\n    u, err := url.Parse(loginURL)\n    return err == nil && u.Query().Get(\"ptsigx\") != \"\"\n}","tryCatchPattern":"ptsigx, uin, err := p.extractLoginInfo(bodyStr)\nif err != nil {\n    if err.Error() == \"未找到ptsigx\" {\n        // login URL shape changed or sign missing; restart QR flow with diagnostics\n        return nil, fmt.Errorf(\"login url lacked ptsigx, refresh QR: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["Log the full extracted login URL when parsing fails","Use url.Parse + Query().Get instead of narrow character-class regexes","URL-decode the callback URL before regex matching","Add regression tests with the latest recorded ptqrlogin URLs"],"tags":["parsing","regex","qq-login"],"backgroundTag":"unexpected-response-shape","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}