feat: add cancelPairingCode() and requestPairingCode() on QR clients (#22449)
* feat: add cancelPairingCode() and allow requestPairingCode() - requestPairingCode() now exposes onCodeReceivedEvent if needed, so it works on clients initialized in QR mode - Add cancelPairingCode() method to stop pairing and return to QR - Update TypeScript definitions * fix(auth): dynamic ADV key in getQR + structural cancelPairingCode the getQR closure captured advSecretKey once during initialize(), but requestpairingcode/cancelPairingCode changes the key in IndexedDB. the stale closure key caused QR scans to fail with HMAC validation error. fix: read key dynamically via WAWebUserPrefsMultiDevice.getADVSecretKey() (synchronous in-memory cache) on every getQR call, matching how WhatsApp web's internal QR component works. cancelpairingcode now mirrors WhatsApp Web's resetLinkDeviceState: refreshqr() restarts WebSocket for fresh refs, then initializeqrlinking() generates a new key. QR emission happens automatically via the existing change:ref listener. --------- Co-authored-by: BenyFilho <168232825+BenyFilho@users.noreply.github.com>
This commit is contained in:
parent
6de0b0dd2b
commit
3e810b6913
2 changed files with 30 additions and 4 deletions
3
index.d.ts
vendored
3
index.d.ts
vendored
|
|
@ -197,6 +197,9 @@ declare namespace WAWebJS {
|
||||||
intervalMs?: number,
|
intervalMs?: number,
|
||||||
): Promise<string>;
|
): Promise<string>;
|
||||||
|
|
||||||
|
/** Cancels an active pairing code session and returns to QR code mode */
|
||||||
|
cancelPairingCode(): Promise<void>
|
||||||
|
|
||||||
/** Force reset of connection state for the client */
|
/** Force reset of connection state for the client */
|
||||||
resetState(): Promise<void>;
|
resetState(): Promise<void>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,8 +255,6 @@ class Client extends EventEmitter {
|
||||||
window.AuthStore.Base64Tools.encodeB64(
|
window.AuthStore.Base64Tools.encodeB64(
|
||||||
registrationInfo.identityKeyPair.pubKey,
|
registrationInfo.identityKeyPair.pubKey,
|
||||||
);
|
);
|
||||||
const advSecretKey =
|
|
||||||
await window.AuthStore.RegistrationUtils.getADVSecretKey();
|
|
||||||
const platform =
|
const platform =
|
||||||
window.AuthStore.RegistrationUtils.DEVICE_PLATFORM;
|
window.AuthStore.RegistrationUtils.DEVICE_PLATFORM;
|
||||||
const getQR = (ref) =>
|
const getQR = (ref) =>
|
||||||
|
|
@ -266,10 +264,11 @@ class Client extends EventEmitter {
|
||||||
',' +
|
',' +
|
||||||
identityKeyB64 +
|
identityKeyB64 +
|
||||||
',' +
|
',' +
|
||||||
advSecretKey +
|
window
|
||||||
|
.require('WAWebUserPrefsMultiDevice')
|
||||||
|
.getADVSecretKey() +
|
||||||
',' +
|
',' +
|
||||||
platform;
|
platform;
|
||||||
|
|
||||||
window.onQRChangedEvent(getQR(window.AuthStore.Conn.ref)); // initial qr
|
window.onQRChangedEvent(getQR(window.AuthStore.Conn.ref)); // initial qr
|
||||||
window.AuthStore.Conn.on('change:ref', (_, ref) => {
|
window.AuthStore.Conn.on('change:ref', (_, ref) => {
|
||||||
window.onQRChangedEvent(getQR(ref));
|
window.onQRChangedEvent(getQR(ref));
|
||||||
|
|
@ -516,6 +515,14 @@ class Client extends EventEmitter {
|
||||||
showNotification = true,
|
showNotification = true,
|
||||||
intervalMs = 180000,
|
intervalMs = 180000,
|
||||||
) {
|
) {
|
||||||
|
await exposeFunctionIfAbsent(
|
||||||
|
this.pupPage,
|
||||||
|
'onCodeReceivedEvent',
|
||||||
|
async (code) => {
|
||||||
|
this.emit(Events.CODE_RECEIVED, code);
|
||||||
|
return code;
|
||||||
|
},
|
||||||
|
);
|
||||||
return await this.pupPage.evaluate(
|
return await this.pupPage.evaluate(
|
||||||
async (phoneNumber, showNotification, intervalMs) => {
|
async (phoneNumber, showNotification, intervalMs) => {
|
||||||
const getCode = async () => {
|
const getCode = async () => {
|
||||||
|
|
@ -553,6 +560,22 @@ class Client extends EventEmitter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels an active pairing code session and returns to QR code mode
|
||||||
|
*/
|
||||||
|
async cancelPairingCode() {
|
||||||
|
await this.pupPage.evaluate(async () => {
|
||||||
|
if (window.codeInterval) {
|
||||||
|
clearInterval(window.codeInterval);
|
||||||
|
window.codeInterval = undefined;
|
||||||
|
}
|
||||||
|
window.require('WAWebLaunchSocketUtils').refreshQR();
|
||||||
|
await window
|
||||||
|
.require('WAWebAltDeviceLinkingApi')
|
||||||
|
.initializeQRLinking();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach event listeners to WA Web
|
* Attach event listeners to WA Web
|
||||||
* Private function
|
* Private function
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue