This repo was created to enable push notifications for Frappe Apps such as Raven.
To be able to run this application, you will need to do the following:
- Clone this project and create a virtual environment
python -m venv env - Install all requirements
pip install -r requirements.txt - Create a Firebase Project & get Service Account credentials Link
- Run this command on the shell
export GOOGLE_APPLICATION_CREDENTIALS="/home/frappe/relay-server/{service-account-file_name}.json"
- Follow Register you app under Step 1 given in the Firebase documentation and obtain the
FIREBASE_CONFIGJSON object. Save it tomy_secrets.py. - Follow this StackOverflow Link to generate a VAPID key. Save it to
my_secrets.py - Generate
API_KEY&API_SECRETand add theAPI_SECRETvalue to themy_secrets.py. - Finally, your
my_secrets.pyshould like this
API_SECRET = 'tIUAGguQH-xajbkcjsd-lsd'
VAPID_PUBLIC_KEY = "Bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
FIREBASE_CONFIG = {
"apiKey": "AIzaSyC3UVxbCkUv3l4PpyWkQZGEuwOds76sdUgk0",
"authDomain": "xxxxxxxx-frappe.firebaseapp.com",
"projectId": "xxxxxxxxx-frappe",
"storageBucket": "xxxxxxxxx-frappe.appspot.com",
"messagingSenderId": "815115xxx703",
"appId": "1:815115xxx703:web:e89fcdadfcf8df09e4852",
"measurementId": "G-XXXXXXXXXG"
}- Change the
USER_DEVICE_MAPkey values to{project_name}_{site_name}whereproject_namecould beravenorhrms&site_nameas your site name while setting up the Frappe bench. - Run the application
- Add the
API_SECRET&API_KEYin ERPNext Push Notification settings and then enable the Push Notification Relay option.
gunicorn app:app -c gunicorn.conf.py- Create a Systemd service file at
/etc/systemd/system/push-relay.serviceand copy the following and replace the paths/filenames accordingly :
# /etc/systemd/system/push-relay.service
[Unit]
Description=Gunicorn instance to server Frappe Push Notification Relay Server
After=network.target
[Service]
User=frappe
Group=www-data
WorkingDirectory=/home/frappe/relay-server
Environment="PATH=/home/frappe/relay-server/env/bin"
Environment="GOOGLE_APPLICATION_CREDENTIALS=/home/frappe/relay-server/{service-account-file_name}.json"
ExecStart=/home/frappe/relay-server/env/bin/gunicorn app:app -c /home/frappe/relay-server/gunicorn.conf.py
[Install]
WantedBy=multi-user.target- Run the following commands
sudo systemctl daemon-reload sudo systemctl enable push-relay sudo systemctl start push-relay
-
In case you are running Frappe instance on localhost, then perform the following steps to avoid CORS issues
-
Run the following commands
pip install flask-cors
-
app.py [add line 8 & 10]
7 from my_secrets import API_SECRET, FIREBASE_CONFIG, VAPID_PUBLIC_KEY, BADGE_ICON + 8 from flask_cors import CORS 9 app = Flask(__name__) + 10 CORS(app, resources={r"/*": {"origins": "*"}}) # This will allow all origins 11 firebase_app = firebase_admin.initialize_app() 12 basic_auth = HTTPBasicAuth() -
firebase_admin/_messaging_encoder.py [ comment line : 507, 508 ]
506 link = result.get('link') - 507 # if link is not None and not link.startswith('https://'): - 508 # raise ValueError('WebpushFCMOptio ns.link must be a HTTPS URL.') 509 return result
-
Restart bench and gunicorn server
-
All API requests require HTTP Basic Auth using your API_KEY as the username and API_SECRET as the password.
curl -u "API_KEY:API_SECRET" http://127.0.0.1:8899/api/...- Type:
Basic Auth - Username:
API_KEY - Password:
API_SECRET
-
Method:
POST -
Endpoint:
/api/method/notification_relay.api.token.add -
Query Parameters:
project_name: project name (e.g.,raven)site_name: site name (e.g.,erpsgs.in)user_id: user email or ID (e.g.,john@example.com)fcm_token: the FCM token from client
-
Example URL:
http://127.0.0.1:8899/api/method/notification_relay.api.token.add?project_name=raven&site_name=erpsgs.in&user_id=john@example.com&fcm_token=abc123
-
Method:
POST -
Endpoint:
/api/method/notification_relay.api.send_notification.user -
Query Parameters:
project_name,site_name,user_id,title,body
-
Request Body (raw JSON):
{
"click_action": "https://example.com",
"notification_icon": "/icon.png"
}- Example URL:
http://127.0.0.1:8899/api/method/notification_relay.api.send_notification.user?project_name=raven&site_name=erpsgs.in&user_id=john@example.com&title=Hello&body=World
-
Method:
POST -
Endpoint:
/api/method/raven_cloud.api.notification.register_site -
Auth: Requires Basic Auth
-
Query Parameters:
site_name: name of the site to register
-
Purpose: Returns the
vapid_public_keyand Firebase configuration required by the client. -
Example Response:
{
"message": {
"vapid_public_key": "<public_key>",
"config": {
"apiKey": "...",
"authDomain": "..."
}
}
}-
Method:
POST -
Endpoint:
/api/method/raven_cloud.api.notification.send -
Query Parameters:
project_name: name of the projectsite_name: name of the sitemessages: a JSON-encoded array of notification objects
-
Notification Format:
[
{
"tokens": ["fcm_token_1", "fcm_token_2"],
"notification": {
"title": "Hello",
"body": "World"
},
"data": {
"notification_icon": "/icon.png"
},
"click_action": "https://example.com",
"image": "https://example.com/image.png"
}
]-
Notes:
click_actionis only included if it starts withhttps://.- You can send to multiple tokens per object.
-
Example Response:
{
"message": {
"success": 200,
"message": "3 notifications sent via 'messages' payload"
}
}$ source env/bin/activate
$ export GOOGLE_APPLICATION_CREDENTIALS="/home/dev/workspace/projects/frappe/relay-server/relay-server/my-firebase.json"
$ gunicorn app:app -c gunicorn.conf.py