WeChat QR Code Scan Login Flow: How scan.get.ts Handles Authentication Polling in wechat-article-exporter
The scan.get.ts endpoint serves as a stateless polling proxy that forwards the client's uuid cookie to WeChat's MP backend, checking whether a QR code has been scanned and confirmed to trigger the final authentication step.
The wechat-article-exporter project implements a server-side QR code authentication system to access WeChat MP (Official Accounts Platform) data without exposing sensitive credentials to the browser. At the heart of this flow lies the server/api/web/login/scan.get.ts handler, which continuously queries WeChat's API to track scan status while maintaining secure session state server-side.
Role of scan.get.ts in the Three-Step QR Code Login Flow
The authentication sequence follows a strict orchestration between three Nuxt server endpoints:
getqrcode.get.ts– Initializes the session by requesting a fresh QR code from WeChat and setting auuidcookie to identify the login attempt.scan.get.ts– Polls the WeChat backend using the storeduuidto detect when the user scans the code and confirms the login.session/[sid].post.ts– Completes the handshake by exchanging the confirmed session ID for an authentication token, storing credentials server-side in the CookieStore, and issuing anauth-keycookie to the client.
Within this pipeline, scan.get.ts functions as the critical bridge between QR code generation and final credential exchange.
Forwarding Poll Requests to WeChat
Located at server/api/web/login/scan.get.ts, the handler extracts all cookies from the incoming request—specifically the uuid set during initialization—and proxies them to WeChat's scan status endpoint:
// server/api/web/login/scan.get.ts
import { getCookiesFromRequest } from '~/server/utils/CookieStore';
import { proxyMpRequest } from '~/server/utils/proxy-request';
export default defineEventHandler(async event => {
// Extract the uuid cookie identifying this login session
const cookie = getCookiesFromRequest(event);
// Forward GET request to WeChat's scan status endpoint
return proxyMpRequest({
event,
method: 'GET',
endpoint: 'https://mp.weixin.qq.com/cgi-bin/scanloginqrcode',
query: {
action: 'ask',
token: '',
lang: 'zh_CN',
f: 'json',
ajax: 1,
},
cookie, // Passes uuid to correlate with the QR code
});
});
The getCookiesFromRequest utility aggregates all client-sent cookies into a formatted Cookie header, while proxyMpRequest (defined in server/utils/proxy-request.ts) transparently forwards the request to WeChat without modifying the response body.
Interpreting WeChat's Scan Status Responses
The endpoint returns raw JSON from WeChat's cgi-bin/scanloginqrcode API, which contains a status field indicating the authentication progress:
0– QR code generated but not yet scanned (pending)1– User has scanned the code but not confirmed the login2– User confirmed the login; ready to proceed to credential exchange
The client implements a polling loop—typically every 2 seconds—calling scan.get.ts until receiving status: 2, at which point it proceeds to the session/[sid].post.ts endpoint to finalize authentication.
Integration with Server-Side CookieStore
While scan.get.ts itself is stateless, it relies on the CookieStore system (server/utils/CookieStore.ts) to maintain session continuity. The uuid cookie passed through this endpoint links the polling request to the specific QR code session created in step 1.
After the scan confirms (status: 2), the subsequent session/[sid].post.ts handler:
- Posts to
https://mp.weixin.qq.com/cgi-bin/bizlogin?action=startlogin - Extracts the authentication token from the redirect URL
- Stores the token and all Set-Cookie headers in the server-side CookieStore via
cookieStore.setCookie - Returns an
auth-keycookie to the client for subsequent API requests
This architecture ensures WeChat credentials never reach the browser, maintaining security while enabling automated content export.
Client-Side Polling Implementation
Frontend applications consume this endpoint through a simple polling pattern:
// Request QR code and store uuid cookie
const { qrcode_url } = await $fetch('/api/web/login/getqrcode');
// Poll until user confirms
async function waitForScan() {
while (true) {
const response = await $fetch('/api/web/login/scan');
// Response: { status: 0, message: "waiting" } or { status: 2, ... }
if (response.status === 2) break; // Confirmed, exit loop
await new Promise(r => setTimeout(r, 2000)); // Wait 2 seconds
}
// Complete login with session ID obtained from previous step
await $fetch(`/api/web/login/session/${sid}`, { method: 'POST' });
// Server now sets auth-key cookie for authenticated requests
}
The scan.get.ts endpoint handles the complexity of WeChat's authentication protocol while presenting a clean JSON interface to the frontend.
Summary
scan.get.tsacts as a transparent proxy between the client and WeChat'scgi-bin/scanloginqrcodeendpoint, enabling secure status polling without exposing WeChat credentials.- The endpoint requires the
uuidcookie set bygetqrcode.get.tsto correlate polling requests with specific QR code sessions. - Status codes (
0,1,2) indicate pending, scanned, and confirmed states respectively, driving the client-side polling logic. - Upon confirmation (
status: 2), control passes tosession/[sid].post.tsto finalize authentication and populate the server-side CookieStore. - This implementation keeps sensitive WeChat session data server-side while allowing the client to track login progress through simple JSON polling.
Frequently Asked Questions
What is the purpose of the scan.get.ts endpoint in wechat-article-exporter?
The scan.get.ts endpoint polls WeChat's MP backend to check whether a user has scanned and confirmed a QR code login. It forwards the client's uuid cookie to WeChat's scanloginqrcode API and returns the raw status response, allowing the frontend to determine when to proceed to the final authentication step.
How does scan.get.ts know which QR code session to check?
The endpoint retrieves the uuid cookie (set during the initial getqrcode.get.ts call) from the incoming request using getCookiesFromRequest. This cookie is passed directly to WeChat's API via proxyMpRequest, enabling WeChat to match the polling request with the correct pending login session.
What do the status codes returned by scan.get.ts mean?
WeChat's API returns three primary status values in the JSON response: 0 indicates the QR code is waiting to be scanned, 1 means the user has scanned but not yet confirmed the login, and 2 signifies the user has confirmed and the session is ready for credential exchange via session/[sid].post.ts.
Why does the server proxy the request instead of calling WeChat directly from the browser?
Direct browser requests to WeChat would expose sensitive cookies and authentication tokens to the client, creating security vulnerabilities. By proxying through scan.get.ts, the server maintains control over session state using the CookieStore utility, ensuring WeChat credentials remain server-side while the client only handles session identifiers like uuid and auth-key.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →