Chore: Add Facebook app set up documentation (#647)

Co-authored-by: Pranav Raj S <pranavrajs@gmail.com>
This commit is contained in:
Sojan Jose 2020-03-28 11:43:02 +05:30 committed by GitHub
parent 209e0a0fb4
commit a3c2d4e5bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 211 additions and 38 deletions

View file

@ -26,3 +26,6 @@ exclude_patterns:
- "node_modules/**/*"
- "lib/tasks/auto_annotate_models.rake"
- "app/test-matchers.js"
- "docs/*"
- "**/*.md"
- "**/*.yml"

View file

@ -22,17 +22,6 @@ POSTGRES_PASSWORD=
RAILS_ENV=development
RAILS_MAX_THREADS=5
#fb app
FB_VERIFY_TOKEN=
FB_APP_SECRET=
FB_APP_ID=
#twitter app
TWITTER_APP_ID=
TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET=
TWITTER_ENVIRONMENT=
#mail
MAILER_SENDER_EMAIL=accounts@chatwoot.com
SMTP_PORT=1025
@ -59,13 +48,25 @@ AWS_REGION=
SENTRY_DSN=
#Log settings
LOG_LEVEL=
LOG_SIZE=
LOG_LEVEL=info
LOG_SIZE=500
# Credentials to access sidekiq dashboard in production
SIDEKIQ_AUTH_USERNAME=
SIDEKIQ_AUTH_PASSWORD=
### This environment variables are only required if you are setting up social media channels
#facebook
FB_VERIFY_TOKEN=
FB_APP_SECRET=
FB_APP_ID=
#twitter
TWITTER_APP_ID=
TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET=
TWITTER_ENVIRONMENT=
#### This environment variables are only required in hosted version which has billing
ENABLE_BILLING=

View file

@ -59,6 +59,8 @@ class Api::V1::Accounts::CallbacksController < Api::BaseController
def long_lived_token(omniauth_token)
koala = Koala::Facebook::OAuth.new(ENV['FB_APP_ID'], ENV['FB_APP_SECRET'])
koala.exchange_access_token_info(omniauth_token)['access_token']
rescue StandardError => e
Rails.logger e
end
def mark_already_existing_facebook_pages(data)

View file

@ -3,7 +3,7 @@ import ApiClient from '../ApiClient';
class FBChannel extends ApiClient {
constructor() {
super('facebook_indicators');
super('facebook_indicators', { accountScoped: true });
}
markSeen({ inboxId, contactId }) {
@ -22,7 +22,7 @@ class FBChannel extends ApiClient {
create(params) {
return axios.post(
`${this.apiVersion}/callbacks/register_facebook_page`,
`${this.url.replace(this.resource, '')}callbacks/register_facebook_page`,
params
);
}

View file

@ -5,9 +5,9 @@
import endPoints from './endPoints';
export default {
fetchFacebookPages(token) {
fetchFacebookPages(token, accountId) {
const urlData = endPoints('fetchFacebookPages');
urlData.params.omniauth_token = token;
return axios.post(urlData.url, urlData.params);
return axios.post(urlData.url(accountId), urlData.params);
},
};

View file

@ -28,7 +28,9 @@ const endPoints = {
},
fetchFacebookPages: {
url: 'api/v1/callbacks/facebook_pages.json',
url(accountId) {
return `api/v1/accounts/${accountId}/callbacks/facebook_pages.json`;
},
params: { omniauth_token: '' },
},

View file

@ -0,0 +1,15 @@
import fbChannel from '../../channel/fbChannel';
import ApiClient from '../../ApiClient';
describe('#FBChannel', () => {
it('creates correct instance', () => {
expect(fbChannel).toBeInstanceOf(ApiClient);
expect(fbChannel).toHaveProperty('get');
expect(fbChannel).toHaveProperty('show');
expect(fbChannel).toHaveProperty('create');
expect(fbChannel).toHaveProperty('update');
expect(fbChannel).toHaveProperty('delete');
expect(fbChannel).toHaveProperty('markSeen');
expect(fbChannel).toHaveProperty('toggleTyping');
});
});

View file

@ -68,6 +68,7 @@
/* global FB */
import { required } from 'vuelidate/lib/validators';
import LoadingState from 'dashboard/components/widgets/LoadingState';
import { mapGetters } from 'vuex';
import ChannelApi from '../../../../../api/channels';
import PageHeader from '../../SettingsSubPageHeader';
import router from '../../../../index';
@ -111,6 +112,12 @@ export default {
getSelectablePages() {
return this.pageList.filter(item => !item.exists);
},
...mapGetters({
currentUser: 'getCurrentUser',
}),
accountId() {
return this.currentUser.account_id;
},
},
created() {
@ -194,13 +201,20 @@ export default {
);
},
fetchPages(_token) {
ChannelApi.fetchFacebookPages(_token)
.then(response => {
this.pageList = response.data.data.page_details;
this.user_access_token = response.data.data.user_access_token;
})
.catch();
async fetchPages(_token) {
try {
const response = await ChannelApi.fetchFacebookPages(
_token,
this.accountId
);
const {
data: { data },
} = response;
this.pageList = data.page_details;
this.user_access_token = data.user_access_token;
} catch (error) {
// Ignore error
}
},
channelParams() {

View file

@ -30,6 +30,18 @@ class Attachment < ApplicationRecord
base_data.merge(file_metadata)
end
def file_url
file.attached? ? url_for(file) : ''
end
def thumb_url
if file.attached? && file.representable?
url_for(file.representation(resize: '250x250'))
else
''
end
end
private
def file_metadata
@ -64,16 +76,4 @@ class Attachment < ApplicationRecord
account_id: account_id
}
end
def file_url
file.attached? ? url_for(file) : ''
end
def thumb_url
if file.attached? && file.representable?
url_for(file.representation(resize: '250x250'))
else
''
end
end
end

View file

@ -32,13 +32,35 @@ class Facebook::SendReplyService
# end
# end
def fb_message_params
def fb_text_message_params
{
recipient: { id: contact.get_source_id(inbox.id) },
message: { text: message.content }
}
end
def fb_attachment_message_params
{
recipient: { id: contact.get_source_id(inbox.id) },
message: {
attachment: {
type: 'image',
payload: {
url: message.attachment.file_url
}
}
}
}
end
def fb_message_params
if message.attachment.blank?
fb_text_message_params
else
fb_attachment_message_params
end
end
def delivery_params
if twenty_four_hour_window_over?
fb_message_params.merge(tag: 'ISSUE_RESOLUTION')

View file

@ -0,0 +1,40 @@
---
path: "/docs/channels/facebook"
title: "How to create Facebook channel?"
---
If you are using self-hosted Chatwoot installation, please configure the Facebook app as described in the [guide to setup Facebook app](/docs/facebook-setup)
**Step 1**. Click on "Add Inbox" button from Settings > Inboxes page.
![fb_create](./images/facebook/inbox_create.png)
**Step 2**. Click on "Facebook" icon.
![list_of_channels](./images/facebook/list_of_channels.png)
**Step 3**. Click on Facebook login button. It will open a new window for you to login.
![create_fb](./images/facebook/login_with_facebook.png)
**Step 4**. Authenticate with Facebook and select the page you want connect, enable all permissions shown in the list, otherwise the app might not work.
![link_account](./images/facebook/link_account.png)
![list_of_pages](./images/facebook/list_of_pages.png)
![list_of_pages](./images/facebook/permissions.png)
![select_page](./images/facebook/select_page.png)
**Step 5**. "Add agents" to your Facebook inbox.
![add_agents](./images/add_agents.png)
**Step 6**. Hooray! You have sucessfully created a Facebook inbox. Whenever a customer sends a message to your Facebook page, you will be able to see it here and manage it.
![finish_inbox](./images/facebook/finish_inbox.png)
**Step 7**. If you want to update the agents who have access to the inbox, you can go to Settings > Inboxes.
![inbox_settings](./images/inbox_settings.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 709 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

View file

@ -0,0 +1,65 @@
---
path: "/docs/facebook-setup"
title: "Setting Up Facebook"
---
### Register A Facebook App
To use Facebook Channel, you have to create an Facebook app in developer portal. You can find more details about creating Facebook channels [here](https://developers.facebook.com/docs/apps/#register)
Once you register your Facebook App, you will have to obtain the `App Id` and `App Secret` . These values will be available in the app settings and will be required while setting up Chatwoot environment variables.
### Configure the Facebook App
1) In the app settings add your `Chatwoot installation url` as your app domain.
2) In the products section in your app settings page, Add Messenger
3) Go to the Messenger settings and configure the call Back URL with `{your_chatwoot_url}/bot`
4) Configure a `verify token`, you will need this value for configuring the chatwoot environment variables
5) You might have to add a Facebook page to your `Access Tokens` section in your Messenger settings page if your app is still in development.
6) You will also have to add your Facebook page to webhooks sections in your messenger settings with all the webhook events checked.
### Configuring the Environment Variables in Chatwoot
Configure the following Chatwoot environment variables with the values you have obtained during the facebook app setup.
```bash
FB_VERIFY_TOKEN=
FB_APP_SECRET=
FB_APP_ID=
```
### Things to note before going into production.
Before you can start using your Facebook app in production, you will have to get it verified by Facebook. Refer the [docs](https://developers.facebook.com/docs/apps/review/) on getting your app verified.
### Developing or Testing Facebook Integration in You Local
Install [ngrok](https://ngrok.com/docs) on your machine. This will be required since Facebook Messenger API's will only communicate via https.
```bash
brew cask install ngrok
```
Configure ngrok to route to your Rails server port.
```bash
ngrok http 3000
```
Go to Facebook developers page and navigate into your app settings. In the app settings, add `localhost` as your app domain.
In the Messenger settings page, configure the callback url with the following value.
```bash
{your_ngrok_url}/bot
```
Update verify token in your Chatwoot environment variables.
You will also have to add a Facebook page to your `Access Tokens` section in your Messenger settings page.
Restart the Chatwoot local server. Your Chatwoot setup will be ready to receive Facebook messages.
### Test your local Setup
1. After finishing the set up above, [create a Facebook inbox](/docs/channels/facebook) after logging in to your Chatwoot Installation.
2. Send a message to your page from Facebook.
3. Wait and confirm incoming requests to `/bot` endpoint in your ngrok screen.

View file

@ -46,6 +46,15 @@ describe Facebook::SendReplyService do
create(:message, message_type: 'outgoing', inbox: facebook_inbox, account: account, conversation: conversation)
expect(bot).to have_received(:deliver)
end
it 'if message with attachment is sent from chatwoot and is outgoing' do
create(:message, message_type: :incoming, inbox: facebook_inbox, account: account, conversation: conversation)
message = build(:message, message_type: 'outgoing', inbox: facebook_inbox, account: account, conversation: conversation)
message.attachment = Attachment.new(account_id: message.account_id, file_type: :image)
message.attachment.file.attach(io: File.open(Rails.root.join('spec/assets/avatar.png')), filename: 'avatar.png', content_type: 'image/png')
message.save!
expect(bot).to have_received(:deliver)
end
end
end
end