From d5c305fae0aec483a25b57723ab6bcc7df07c7cd Mon Sep 17 00:00:00 2001 From: mmhospedagem Date: Thu, 10 Sep 2026 11:16:57 -0300 Subject: [PATCH] fix(message): align interactive button stanza metadata --- .../WaMessageDispatchCoordinator.ts | 11 ++++++++- .../node/builders/__tests__/builders.test.ts | 24 ++++++------------- src/transport/node/builders/message.ts | 18 ++++++++++---- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/client/coordinators/WaMessageDispatchCoordinator.ts b/src/client/coordinators/WaMessageDispatchCoordinator.ts index 9c957bea..c3e91606 100644 --- a/src/client/coordinators/WaMessageDispatchCoordinator.ts +++ b/src/client/coordinators/WaMessageDispatchCoordinator.ts @@ -637,6 +637,7 @@ export class WaMessageDispatchCoordinator { const outboundAttrs = resolveOutboundMessageAttrs(messageWithIcdc) const buttonAddonKind = outboundAttrs.buttonAddonKind const buttonAddonNode = buttonAddonKind ? buildButtonAddonNode(buttonAddonKind) : undefined + const isInteractiveNativeFlow = !!unwrapMessage(messageWithIcdc).interactiveMessage // when a companion is attached the stanza must advertise type=text and // omit enc.mediatype; sending type=media + mediatype=list/button alongside the // companion is rejected by the server as SMAX_INVALID (479). @@ -663,7 +664,15 @@ export class WaMessageDispatchCoordinator { mediatype, decryptFail, customNodes: customNodes.length > 0 ? customNodes : undefined, - sendOptions + sendOptions: isInteractiveNativeFlow + ? { + ...sendOptions, + additionalAttributes: { + ...sendOptions.additionalAttributes, + device_fanout: 'false' + } + } + : sendOptions } const peerRecipientPn = isGroup diff --git a/src/transport/node/builders/__tests__/builders.test.ts b/src/transport/node/builders/__tests__/builders.test.ts index 6c33886e..fcf9c1a5 100644 --- a/src/transport/node/builders/__tests__/builders.test.ts +++ b/src/transport/node/builders/__tests__/builders.test.ts @@ -776,6 +776,9 @@ test('message builders create fanout nodes and validate participant requirements const interactiveAddon = buildButtonAddonNode('interactive') assert.equal(interactiveAddon.tag, 'biz') + assert.equal(interactiveAddon.attrs.actual_actors, '2') + assert.equal(interactiveAddon.attrs.host_storage, '2') + assert.match(interactiveAddon.attrs.privacy_mode_ts ?? '', /^\d+$/) if (!Array.isArray(interactiveAddon.content)) throw new Error('expected biz children') const interactiveChild = interactiveAddon.content[0] assert.equal(interactiveChild.tag, 'interactive') @@ -790,25 +793,12 @@ test('message builders create fanout nodes and validate participant requirements const pixAddon = buildButtonAddonNode('payment_info') assert.equal(pixAddon.tag, 'biz') - if (!Array.isArray(pixAddon.content)) throw new Error('expected biz children') - const pixInteractive = pixAddon.content[0] - assert.equal(pixInteractive.tag, 'interactive') - assert.equal(pixInteractive.attrs.type, 'native_flow') - if (!Array.isArray(pixInteractive.content)) { - throw new Error('expected native_flow child') - } - assert.equal(pixInteractive.content[0].tag, 'native_flow') - assert.equal(pixInteractive.content[0].attrs.name, 'payment_info') - assert.equal(pixInteractive.content[0].attrs.v, undefined) + assert.deepEqual(pixAddon.attrs, { native_flow_name: 'payment_info' }) + assert.equal(pixAddon.content, undefined) const reviewAddon = buildButtonAddonNode('order_details') - if (!Array.isArray(reviewAddon.content)) throw new Error('expected biz children') - const reviewInteractive = reviewAddon.content[0] - if (!Array.isArray(reviewInteractive.content)) { - throw new Error('expected native_flow child') - } - assert.equal(reviewInteractive.content[0].attrs.name, 'order_details') - assert.equal(reviewInteractive.content[0].attrs.v, undefined) + assert.deepEqual(reviewAddon.attrs, { native_flow_name: 'order_details' }) + assert.equal(reviewAddon.content, undefined) const fanoutWithAddon = buildDirectMessageFanoutNode({ to: '5511@s.whatsapp.net', diff --git a/src/transport/node/builders/message.ts b/src/transport/node/builders/message.ts index e250299b..06999c7c 100644 --- a/src/transport/node/builders/message.ts +++ b/src/transport/node/builders/message.ts @@ -190,13 +190,21 @@ export function buildButtonAddonNode(kind: WaButtonAddonKind): BinaryNode { } } - const nativeFlowName = kind === 'payment_info' || kind === 'order_details' ? kind : 'mixed' - const nativeFlowAttrs: Record = - nativeFlowName === 'mixed' ? { v: '9', name: 'mixed' } : { name: nativeFlowName } + if (kind === 'payment_info' || kind === 'order_details') { + return { + tag: WA_NODE_TAGS.BIZ, + attrs: { native_flow_name: kind }, + content: undefined + } + } return { tag: WA_NODE_TAGS.BIZ, - attrs: {}, + attrs: { + actual_actors: '2', + host_storage: '2', + privacy_mode_ts: Math.floor(Date.now() / 1000).toString() + }, content: [ { tag: WA_NODE_TAGS.INTERACTIVE, @@ -204,7 +212,7 @@ export function buildButtonAddonNode(kind: WaButtonAddonKind): BinaryNode { content: [ { tag: WA_NODE_TAGS.NATIVE_FLOW, - attrs: nativeFlowAttrs, + attrs: { v: '9', name: 'mixed' }, content: undefined } ]