diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json index 821e2ecbd..4006212a3 100644 --- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json +++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json @@ -280,6 +280,11 @@ "SECURE_AUTH": "Secure OAuth based authentication", "AUTO_CONFIG": "Automatic webhook and phone number configuration" }, + "LEARN_MORE": { + "TEXT": "To learn more about integrated signup, pricing, and limitations, visit", + "LINK_TEXT": "this link.", + "LINK_URL": "https://developers.facebook.com/docs/whatsapp/embedded-signup/custom-flows/onboarding-business-app-users#limitations" + }, "SUBMIT_BUTTON": "Connect with WhatsApp Business", "AUTH_PROCESSING": "Authenticating with Meta", "WAITING_FOR_BUSINESS_INFO": "Please complete business setup in the Meta window...", diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/WhatsappEmbeddedSignup.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/WhatsappEmbeddedSignup.vue index 384082b71..583ca2413 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/WhatsappEmbeddedSignup.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/WhatsappEmbeddedSignup.vue @@ -107,7 +107,7 @@ const completeSignupFlow = async businessDataParam => { code: authCode.value, business_id: businessDataParam.business_id, waba_id: businessDataParam.waba_id, - phone_number_id: businessDataParam.phone_number_id, + phone_number_id: businessDataParam?.phone_number_id || '', }; const responseData = await store.dispatch( @@ -127,7 +127,10 @@ const completeSignupFlow = async businessDataParam => { // Message handling const handleEmbeddedSignupData = async data => { - if (data.event === 'FINISH') { + if ( + data.event === 'FINISH' || + data.event === 'FINISH_WHATSAPP_BUSINESS_APP_ONBOARDING' + ) { const businessDataLocal = data.data; if (isValidBusinessData(businessDataLocal)) { @@ -262,6 +265,25 @@ onBeforeUnmount(() => { +
<%= @installation_configs[key]&.dig('description') %> diff --git a/config/installation_config.yml b/config/installation_config.yml index 53251fc3c..01799e830 100644 --- a/config/installation_config.yml +++ b/config/installation_config.yml @@ -10,7 +10,8 @@ # locked: if you don't specify locked attribute in yaml, the default value will be true, # which means the particular config will be locked and won't be available in `super_admin/installation_configs` # premium: These values get overwritten unless the user is on a premium plan -# type: The type of the config. Default is text, boolean is also supported +# type: The type of the config. Default is text, select and boolean are also supported +# options: For select types, its required to have options for the select in the following pattern: "option_value":"Human readable option" # ------- Branding Related Config ------- # - name: INSTALLATION_NAME diff --git a/spec/services/whatsapp/webhook_setup_service_spec.rb b/spec/services/whatsapp/webhook_setup_service_spec.rb index 89beca922..7cee115c2 100644 --- a/spec/services/whatsapp/webhook_setup_service_spec.rb +++ b/spec/services/whatsapp/webhook_setup_service_spec.rb @@ -24,25 +24,19 @@ describe Whatsapp::WebhookSetupService do end describe '#perform' do - context 'when all operations succeed' do + context 'when phone number is NOT verified (should register)' do before do + allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(false) allow(SecureRandom).to receive(:random_number).with(900_000).and_return(123_456) allow(api_client).to receive(:register_phone_number).with('123456789', 223_456) allow(api_client).to receive(:subscribe_waba_webhook) - .with(waba_id, anything, 'test_verify_token') - .and_return({ 'success' => true }) + .with(waba_id, anything, 'test_verify_token').and_return({ 'success' => true }) allow(channel).to receive(:save!) end - it 'registers the phone number' do + it 'registers the phone number and sets up webhook' do with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do expect(api_client).to receive(:register_phone_number).with('123456789', 223_456) - service.perform - end - end - - it 'sets up webhook subscription' do - with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do expect(api_client).to receive(:subscribe_waba_webhook) .with(waba_id, 'https://app.chatwoot.com/webhooks/whatsapp/+1234567890', 'test_verify_token') service.perform @@ -50,33 +44,71 @@ describe Whatsapp::WebhookSetupService do end end - context 'when phone registration fails' do + context 'when phone number IS verified (should NOT register)' do before do - allow(SecureRandom).to receive(:random_number).with(900_000).and_return(123_456) - allow(api_client).to receive(:register_phone_number) - .and_raise('Registration failed') + allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(true) allow(api_client).to receive(:subscribe_waba_webhook) - .and_return({ 'success' => true }) + .with(waba_id, anything, 'test_verify_token').and_return({ 'success' => true }) end - it 'continues with webhook setup' do + it 'does NOT register phone, but sets up webhook' do with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do + expect(api_client).not_to receive(:register_phone_number) + expect(api_client).to receive(:subscribe_waba_webhook) + .with(waba_id, 'https://app.chatwoot.com/webhooks/whatsapp/+1234567890', 'test_verify_token') + service.perform + end + end + end + + context 'when phone_number_verified? raises error' do + before do + allow(api_client).to receive(:phone_number_verified?).with('123456789').and_raise('API down') + allow(SecureRandom).to receive(:random_number).with(900_000).and_return(123_456) + allow(api_client).to receive(:register_phone_number) + allow(api_client).to receive(:subscribe_waba_webhook).and_return({ 'success' => true }) + allow(channel).to receive(:save!) + end + + it 'tries to register phone and proceeds with webhook setup' do + with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do + expect(api_client).to receive(:register_phone_number) expect(api_client).to receive(:subscribe_waba_webhook) expect { service.perform }.not_to raise_error end end end - context 'when webhook setup fails' do + context 'when phone registration fails (not blocking)' do before do + allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(false) + allow(SecureRandom).to receive(:random_number).with(900_000).and_return(123_456) + allow(api_client).to receive(:register_phone_number).and_raise('Registration failed') + allow(api_client).to receive(:subscribe_waba_webhook).and_return({ 'success' => true }) + allow(channel).to receive(:save!) + end + + it 'continues with webhook setup even if registration fails' do + with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do + expect(api_client).to receive(:register_phone_number) + expect(api_client).to receive(:subscribe_waba_webhook) + expect { service.perform }.not_to raise_error + end + end + end + + context 'when webhook setup fails (should raise)' do + before do + allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(false) allow(SecureRandom).to receive(:random_number).with(900_000).and_return(123_456) allow(api_client).to receive(:register_phone_number) - allow(api_client).to receive(:subscribe_waba_webhook) - .and_raise('Webhook failed') + allow(api_client).to receive(:subscribe_waba_webhook).and_raise('Webhook failed') end it 'raises an error' do with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do + expect(api_client).to receive(:register_phone_number) + expect(api_client).to receive(:subscribe_waba_webhook) expect { service.perform }.to raise_error(/Webhook setup failed/) end end @@ -84,24 +116,25 @@ describe Whatsapp::WebhookSetupService do context 'when required parameters are missing' do it 'raises error when channel is nil' do - service = described_class.new(nil, waba_id, access_token) - expect { service.perform }.to raise_error(ArgumentError, 'Channel is required') + service_invalid = described_class.new(nil, waba_id, access_token) + expect { service_invalid.perform }.to raise_error(ArgumentError, 'Channel is required') end it 'raises error when waba_id is blank' do - service = described_class.new(channel, '', access_token) - expect { service.perform }.to raise_error(ArgumentError, 'WABA ID is required') + service_invalid = described_class.new(channel, '', access_token) + expect { service_invalid.perform }.to raise_error(ArgumentError, 'WABA ID is required') end it 'raises error when access_token is blank' do - service = described_class.new(channel, waba_id, '') - expect { service.perform }.to raise_error(ArgumentError, 'Access token is required') + service_invalid = described_class.new(channel, waba_id, '') + expect { service_invalid.perform }.to raise_error(ArgumentError, 'Access token is required') end end context 'when PIN already exists' do before do channel.provider_config['verification_pin'] = 123_456 + allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(false) allow(api_client).to receive(:register_phone_number) allow(api_client).to receive(:subscribe_waba_webhook).and_return({ 'success' => true }) allow(channel).to receive(:save!)