Skip to content

fix(channels/wechat): encode qrcode_img_content so the login QR is scannable#6086

Merged
houko merged 2 commits into
mainfrom
fix/wechat-qr-img-content
Jun 11, 2026
Merged

fix(channels/wechat): encode qrcode_img_content so the login QR is scannable#6086
houko merged 2 commits into
mainfrom
fix/wechat-qr-img-content

Conversation

@houko

@houko houko commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Symptom

Scanning the WeChat QR code shown in the dashboard does not log in — the WeChat app shows a meaningless string of characters instead of a login confirmation.

Root cause

iLink's GET /ilink/bot/get_bot_qrcode returns two relevant fields:

  • qrcode — an opaque status-poll key, passed to get_qrcode_status?qrcode=…. It is not scannable.
  • qrcode_img_content — the payload the WeChat app actually decodes on scan (what makes WeChat recognise it as a login).

The pre-migration in-process Rust adapter surfaced qrcode_img_content as the QR payload — that was the explicit fix in #1560 / #1572 ("use iLink qr_url for WeChat QR code so WeChat can recognise the scan"). Its dashboard handler did:

let qrcode     = body["qrcode"].as_str()             // poll key
let qrcode_url = body["qrcode_img_content"].as_str() // scannable payload
json!({ "qr_code": qrcode, "qr_url": qrcode_url })   // front-end encodes qr_url

The WeChat → sidecar migration (#5421) dropped qrcode_img_content. _qr_login read only qrcode and encoded that opaque poll token into the QR, with a comment claiming "iLink does not surface a pre-formed deep-link URL." So the dashboard canvas encodes the poll key, WeChat can't recognise it as a login, and the user sees a plain string — re-introducing the exact bug #1572 had fixed.

Fix

sdk/python/librefang/sidecar/adapters/wechat.py::_qr_login:

  • Read qrcode_img_content and emit it as the qr_ready payload (qr_code), which the dashboard encodes into the scannable canvas.
  • Keep using the qrcode token for status polling (get_qrcode_status).
  • If iLink ever omits qrcode_img_content, fall back to the token with a WARN (degraded — renders something rather than crashing) instead of silently shipping an unscannable QR.
  • Corrected the module docstring + the inline comment that wrongly claimed the raw qrcode string is what operators scan.

Tests

Scope

Python sidecar only; independent of the other open channel PRs (#6085 describe-probe, #6083 goal-runner). No Rust changes.

@github-actions github-actions Bot added size/M 50-249 lines changed area/docs Documentation and guides area/sdk JavaScript and Python SDKs and removed size/M 50-249 lines changed labels Jun 11, 2026
@houko
houko enabled auto-merge (squash) June 11, 2026 12:04
@github-actions github-actions Bot added has-conflicts PR has merge conflicts that need resolution size/M 50-249 lines changed labels Jun 11, 2026
Evan and others added 2 commits June 11, 2026 21:13
The WeChat sidecar's QR login encoded the iLink `qrcode` field into the dashboard QR canvas.
But `qrcode` is only the opaque status-poll key — the payload the WeChat app decodes on scan is `qrcode_img_content`.
Encoding the poll token makes WeChat render the QR as a plain-text string rather than a login prompt.

The pre-migration in-process Rust adapter surfaced `qrcode_img_content` as the QR payload (the original #1560 / #1572 fix: "use iLink qr_url so WeChat can recognise the scan").
The sidecar migration (#5421) dropped that field and fell back to encoding the token, re-introducing the exact bug #1572 had fixed.

`_qr_login` now reads `qrcode_img_content` and emits it as the `qr_ready` payload, falling back to the token with a WARN only if iLink omits the field; the `qrcode` token still drives status polling.

Tests: updated the happy-path assertion to require `qrcode_img_content`, added a degraded-fallback case; full sdk/python suite 1874 passed.
Three tests that exercise different failure/edge paths all used a mock
iLink response without `qrcode_img_content`, causing the fallback WARN
introduced alongside the fix to fire spuriously on every run.
Each affected test now uses a realistic response that matches the happy
path, so the warning stays silent unless the field is genuinely absent.
@houko
houko force-pushed the fix/wechat-qr-img-content branch from dd6214f to ed22529 Compare June 11, 2026 12:13
@github-actions github-actions Bot added ready-for-review PR is ready for maintainer review and removed has-conflicts PR has merge conflicts that need resolution labels Jun 11, 2026
@houko
houko merged commit 01f8199 into main Jun 11, 2026
31 checks passed
@houko
houko deleted the fix/wechat-qr-img-content branch June 11, 2026 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs Documentation and guides area/sdk JavaScript and Python SDKs ready-for-review PR is ready for maintainer review size/M 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants