Compare commits

...

1 Commits

Author SHA1 Message Date
Renato Alcara 62dcca488c 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 <noreply@anthropic.com>
2026-03-02 22:00:13 -03:00
2 changed files with 24 additions and 16 deletions
+13 -4
View File
@@ -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({
+11 -12
View File
@@ -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