feat(whatsapp): add optional phone_number_id parameter to media retrieval API (#11823)

## Description

This pull request introduces an optional parameter, `phone_number_id`,
to the WhatsApp API call responsible for retrieving media. The addition
of this parameter allows for greater flexibility when interacting with
the WhatsApp API, as it can now accommodate scenarios where specifying a
particular phone number ID is necessary. This change is backward
compatible and does not affect existing functionality if the parameter
is not provided.

Fixes # (issue)

## Type of change

- [x] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

The changes were tested locally by invoking the WhatsApp media retrieval
API with and without the `phone_number_id` parameter. Both scenarios
were verified to ensure that:

- When `phone_number_id` is provided, the API call includes the
parameter and functions as expected.
- When `phone_number_id` is omitted, the API call continues to work as
before, maintaining backward compatibility.

No errors or warnings were observed during testing, and all relevant
unit tests passed successfully.

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
Eduardo Policarpo
2025-09-23 00:46:59 -03:00
committed by GitHub
parent 8162473eb6
commit 46b75e1b03
3 changed files with 70 additions and 25 deletions

View File

@@ -9,7 +9,13 @@ class Whatsapp::IncomingMessageWhatsappCloudService < Whatsapp::IncomingMessageB
end
def download_attachment_file(attachment_payload)
url_response = HTTParty.get(inbox.channel.media_url(attachment_payload[:id]), headers: inbox.channel.api_headers)
url_response = HTTParty.get(
inbox.channel.media_url(
attachment_payload[:id],
inbox.channel.provider_config['phone_number_id']
),
headers: inbox.channel.api_headers
)
# This url response will be failure if the access token has expired.
inbox.channel.authorization_error! if url_response.unauthorized?
Down.download(url_response.parsed_response['url'], headers: inbox.channel.api_headers) if url_response.success?

View File

@@ -62,8 +62,10 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi
{ 'Authorization' => "Bearer #{whatsapp_channel.provider_config['api_key']}", 'Content-Type' => 'application/json' }
end
def media_url(media_id)
"#{api_base_path}/v13.0/#{media_id}"
def media_url(media_id, phone_number_id = nil)
url = "#{api_base_path}/v13.0/#{media_id}"
url += "?phone_number_id=#{phone_number_id}" if phone_number_id
url
end
def api_base_path

View File

@@ -29,32 +29,23 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do
context 'when valid attachment message params' do
it 'creates appropriate conversations, message and contacts' do
stub_request(:get, whatsapp_channel.media_url('b1c68f38-8734-4ad3-b4a1-ef0c10d683')).to_return(
status: 200,
body: {
messaging_product: 'whatsapp',
url: 'https://chatwoot-assets.local/sample.png',
mime_type: 'image/jpeg',
sha256: 'sha256',
file_size: 'SIZE',
id: 'b1c68f38-8734-4ad3-b4a1-ef0c10d683'
}.to_json,
headers: { 'content-type' => 'application/json' }
)
stub_request(:get, 'https://chatwoot-assets.local/sample.png').to_return(
status: 200,
body: File.read('spec/assets/sample.png')
)
stub_media_url_request
stub_sample_png_request
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
expect(Contact.all.first.name).to eq('Sojan Jose')
expect(whatsapp_channel.inbox.messages.first.content).to eq('Check out my product!')
expect(whatsapp_channel.inbox.messages.first.attachments.present?).to be true
expect_conversation_created
expect_contact_name
expect_message_content
expect_message_has_attachment
end
it 'increments reauthorization count if fetching attachment fails' do
stub_request(:get, whatsapp_channel.media_url('b1c68f38-8734-4ad3-b4a1-ef0c10d683')).to_return(
stub_request(
:get,
whatsapp_channel.media_url(
'b1c68f38-8734-4ad3-b4a1-ef0c10d683',
whatsapp_channel.provider_config['phone_number_id']
)
).to_return(
status: 401
)
@@ -115,4 +106,50 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do
end
end
end
# Métodos auxiliares para reduzir o tamanho do exemplo
def stub_media_url_request
stub_request(
:get,
whatsapp_channel.media_url(
'b1c68f38-8734-4ad3-b4a1-ef0c10d683',
whatsapp_channel.provider_config['phone_number_id']
)
).to_return(
status: 200,
body: {
messaging_product: 'whatsapp',
url: 'https://chatwoot-assets.local/sample.png',
mime_type: 'image/jpeg',
sha256: 'sha256',
file_size: 'SIZE',
id: 'b1c68f38-8734-4ad3-b4a1-ef0c10d683'
}.to_json,
headers: { 'content-type' => 'application/json' }
)
end
def stub_sample_png_request
stub_request(:get, 'https://chatwoot-assets.local/sample.png').to_return(
status: 200,
body: File.read('spec/assets/sample.png')
)
end
def expect_conversation_created
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
end
def expect_contact_name
expect(Contact.all.first.name).to eq('Sojan Jose')
end
def expect_message_content
expect(whatsapp_channel.inbox.messages.first.content).to eq('Check out my product!')
end
def expect_message_has_attachment
expect(whatsapp_channel.inbox.messages.first.attachments.present?).to be true
end
end