From 62dcca488c4d55ab0912cb2781c30ca61c134c68 Mon Sep 17 00:00:00 2001 From: Renato Alcara Date: Mon, 2 Mar 2026 22:00:13 -0300 Subject: [PATCH] fix: use MACOS UserAgent for Android browser to fix pair code registration The web protocol (WA\x06\x03) requires a web-compatible UserAgent. Using SMB_ANDROID in the UserAgent caused pair code registration to fail with "cannot connect device" even though the phone confirmation appeared. The Android identity is now only set in DeviceProps.platformType (ANDROID_PHONE) in the registration node, which correctly determines the display name in "Linked Devices" as "Android (14)". Changes: - getUserAgent(): always returns MACOS platform and Desktop device - getClientPayload(): always includes webInfo (no longer skipped for Android) - Remove unused isAndroidBrowser import from validate-connection.ts - Update pair code comments documenting tested platform IDs - Add structured logging to pair code request Co-Authored-By: Claude Opus 4.6 --- src/Socket/socket.ts | 17 +++++++++++++---- src/Utils/validate-connection.ts | 23 +++++++++++------------ 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index 032b6ab4..0fdc80d6 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -1351,14 +1351,23 @@ export const makeSocket = (config: SocketConfig) => { name: '~' } - // Pair code with Android browser doesn't work (WA server rejects the - // companion registration). When Android is detected, fall back to the - // Chrome/macOS platform values that are known to work. + // Pair code companion_platform_id must be Chrome (1) when using Android + // browser preset. ANDROID_PHONE (16) causes silent timeout (server ignores), + // UWP (21) causes "cannot connect device" rejection. Only Chrome (1) works + // for pair code via web protocol (WA\x06\x03). The device still appears as + // "Android" in linked devices because DeviceProps.platformType=ANDROID_PHONE + // is set separately in the registration node. const isAndroid = isAndroidBrowser(browser) const pairPlatformId = isAndroid ? getPlatformId('Chrome') : getPlatformId(browser[1]) const pairPlatformDisplay = isAndroid ? 'Chrome (Mac OS)' : `${browser[1]} (${browser[0]})` - logger.info(`\uD83D\uDD17 Pair code requested | companion: ${pairPlatformDisplay} | ${isAndroid ? 'android override \u2192 Chrome' : 'native platform'}`) + logger.info({ + pairCode: pairingCode, + jid: authState.creds.me.id, + companionPlatformId: pairPlatformId, + companionPlatformDisplay: pairPlatformDisplay, + isAndroid, + }, `pair code requested | companion: ${pairPlatformDisplay} | ${isAndroid ? 'android override -> Chrome' : 'native platform'}`) ev.emit('creds.update', authState.creds) await sendNode({ diff --git a/src/Utils/validate-connection.ts b/src/Utils/validate-connection.ts index 2091cc56..af509e78 100644 --- a/src/Utils/validate-connection.ts +++ b/src/Utils/validate-connection.ts @@ -9,25 +9,27 @@ import { } from '../Defaults' import type { AuthenticationCreds, SignalCreds, SocketConfig } from '../Types' import { type BinaryNode, getBinaryNodeChild, jidDecode, S_WHATSAPP_NET } from '../WABinary' -import { isAndroidBrowser } from './browser-utils' import { Curve, hmacSign } from './crypto' import { encodeBigEndian } from './generics' import { createSignalIdentity } from './signal' const getUserAgent = (config: SocketConfig): proto.ClientPayload.IUserAgent => { - const isAndroid = isAndroidBrowser(config.browser) + // Always use MACOS/Desktop identity for UserAgent — we connect via web + // protocol (WA\x06\x03) so the server expects a web-like UserAgent. + // Using SMB_ANDROID here causes pair code registration to fail with + // "não é possível conectar" even though the phone shows the confirmation. + // Android identity is only set in DeviceProps (registration node) which + // determines the display name in "Linked Devices". return { appVersion: { primary: config.version[0], secondary: config.version[1], tertiary: config.version[2] }, - platform: isAndroid - ? proto.ClientPayload.UserAgent.Platform.SMB_ANDROID - : proto.ClientPayload.UserAgent.Platform.MACOS, + platform: proto.ClientPayload.UserAgent.Platform.MACOS, releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE, - osVersion: isAndroid ? config.browser[0] : '0.1', - device: isAndroid ? 'Android' : 'Desktop', + osVersion: '0.1', + device: 'Desktop', osBuildNumber: '0.1', localeLanguageIso6391: 'en', mnc: '000', @@ -58,11 +60,8 @@ const getClientPayload = (config: SocketConfig) => { const payload: proto.IClientPayload = { connectType: proto.ClientPayload.ConnectType.WIFI_UNKNOWN, connectReason: proto.ClientPayload.ConnectReason.USER_ACTIVATED, - userAgent: getUserAgent(config) - } - - if (!isAndroidBrowser(config.browser)) { - payload.webInfo = getWebInfo(config) + userAgent: getUserAgent(config), + webInfo: getWebInfo(config) } return payload