Introduction
There is reference for PC Pusher, version 6.0
The PC Pusher is a fast microservice application with the ability to work under high load. It allows sending pushes to all device types like iOS, Android, Huawei.
PC Pusher supports secure uploading data to mobile device and can send a notification delivery report to the application system.
PC Pusher uses
- Redis as external cache-service
- STOMP protocol for interchange between PC Pusher components. So, any message broker (like RabbitMQ, ActiveMQ, ArtemisMQ, HornetMQ and others) with STOMP-protocol support can be used.
PC Pusher can be deployed as single-application as well. In this case, in-memmory STOMP message broker built-in will be used.
PC Pusher contains two API interfaces to interact with:
- PC Pusher 5.2 API
- PC Inform 2.0 API
PC Pusher contains following microservices:
- PushReceiver
- StompBrokerRelay
- Senders: AppleSender, HuaweiSender, GoogleSender
- Payloader
- Callbacker
- StatusChanger
General flow description
Principles
PC Pusher process in general looks like following:
- An Application sends via HTTP-POST request with
push-task
to PushReceiver - PushReceiver processes task and sends it to a proper Sender
- Sender sends message to a mobile device through cloud-service
- The mobile device receives the push-message and sends HTTP-POST request to Payloader to recieve
push-task-payload
- Payloader provides
push-task-payload
to the mobile devices and sends notification to Callbacker - Callbacker sends infromation about
push-task-status
to the Application via HTTP-POST request
Workflow
PC Pusher process work flow is shown in Figure-1 bellow (clickable).
Workflow steps
Prerequisites
- In case of external message broker
StompBrokerRelay
service connects to a message broker - Other services connects to the message broker queues via
StompBrokerRelay
:/queue/android
/queue/apple
/queue/huawei
/queue/notification
/queue/callbacks
Steps description
- An Application sends
push-task
via HTTP-POST request toPushReceiver
. The task can contain base64-encodedpayload
PushReceiver
processes task:- creates
notification
object - adds randomly generated
pcinform_uuid
to push-message - stores it to
Redis
- chooses proper sender queue
- sends prepared task to choosen queue
- creates
- Sender
- chooses proper credentials to communicate with cloud-service (APNS/Firebase/HMS)
- sends push-message to the cloud service
- sends
notification
object with renewed status toStatusChanger
via/notification/queue
StatusChanger
receivesnotification
and renewsnotification
status inRedis
Following steps are optional and it used to control push-delivery and/or provide additinal payload
via authenticated channel
- Mobile device
- receives push-message from cloud sevice
- calculates
authentication code
=HMAC-SHA256(sha256(device_token), pcinform_uuid)
, hex-string representation - requests
Payloader
for notificationpayload
, request is authenticated byauthentication code
Payloader
- receives request from mobile devices
- calculates and verifies
authentication code
, returnsHTTP 401 ('Not Authorized')
in case of fail - gets
payload
fromRedis
- returns
HTTP 204 ('No Content')
orHTTP 200 ('OK')
- sends
callback-task
to/queue/callbacks
to send callback about push delivered successfuly status - sends
notification
object with renewed status toStatusChanger
via/notification/queue
Callbacker
sends HTTP-POST callback to the Application
API Description
PC Pusher 5.2 API
Send templated push
endpoint: {{pc-pusher-host}}/pc-pusher-api/send_push
method: POST
Request Sample
{
"system_id":"ba44ac5f-04fc-4f67-be3a-89aa91e1cb67",
"user_id":"rest-api-test-8b395013-b24b-447e-8c18-cc99cab84bee",
"transaction_id":"sa119c5f-7fsc-3f63-h63h-91aa91e1cb67",
"device_id":"e32f85ebb55556aab154fef6eaf884c4a5b3c3ba0c8de06156df90d7c25ba98c",
"device_type":"iOS",
"appId":"org.paycontrol.app"
}
Response Sample
{
"answer_type": "notification_info",
"answer": {
"result": {
"error_message": "Success",
"error_code": 0
},
"notification_info": {
"notification_id": "2f03cda8-06aa-4b9e-961d-bf68a7a867a1",
"status": "NEW"
}
},
"answer_version": 3
}
This request is to send templated push-notification. Usually used by PC Server to notify mobile app about new transaction.
Request params:
Field name | Mandatory | Description | Type |
---|---|---|---|
system_id | yes | PC System Id | String |
user_id | no | PC User Id | String |
transaction_id | no | PC Transaction Id | String |
device_id | yes | Device push token | String |
device_type | yes | Device Type (iOS, Android, Huawei) | String |
appId | yes | bundle/package name | String |
Response contains notification_info
object:
Field | Description | Type |
---|---|---|
notification_id | UUID of notification object | String |
status | notification status | String |
Send custom push (-es)
endpoint: {{pc-pusher-host}}/pc-pusher-api/send_push_message
method: POST
Request Sample
{
"system_id":"ba44ac5f-04fc-4f67-be3a-89aa91e1cb67",
"user_id":"rest-api-test-8b395013-b24b-447e-8c18-cc99cab84bee",
"transaction_id": "ad88d1b6-e611-42d9-834f-b9c4a31aabcc",
"device_id": "etrWwLT7nOG2nDC1F_e-9traJqQtxDDHFbQiyCZGQnAwqj82E1sNGJiDyZCa7g2hfk56B_7XHwqKk25Vi5zBgYtime1p1TpcFoRjxsq34s",
"device_type": "Android",
"app_id": "org.paycontrol.app",
"content": {
"messages": [
{
"to": "%DEVICE_TOKEN%",
"notification": {
"tag": "%USER_ID%",
"title": "There is a new transaction",
"body": "You have transactions to confirm",
"icon": "paycontrol_push",
"sound": "default"
},
"data": {
"type": "PayControl_v2"
}
}
]
}
}
Response Sample
{
"answer_type": "notification_info",
"answer": {
"result": {
"error_message": "Success",
"error_code": 0
},
"notification_info": {
"notification_id": "2f03cda8-06aa-4b9e-961d-bf68a7a867a1",
"status": "NEW"
}
},
"answer_version": 3
}
The request is used to send custom push or set of pushes to specified mobile app.
Request params:
Field name | Mandatory | Description | Type |
---|---|---|---|
system_id | yes | PC System Id | String |
user_id | no | PC User Id | String |
transaction_id | no | PC Transaction Id | String |
device_id | yes | Device push token | String |
device_type | yes | Device Type (iOS, Android, Huawei) | String |
appId | yes | bundle/package name | String |
messages | yes | push-messages with specific for cloud-service (APNS/Firebase/Huawei) structure | JSON-Array |
Response is the same as for Send templated push.
Get notification status
endpoint: {{pc-pusher-host}}/pc-pusher-api/notification/{{notification_id}}
method: GET
Response Sample
{
"answer_type": "notification_info",
"answer": {
"result": {
"error_message": "Success",
"error_code": 0
},
"notification_info": {
"notification_id": "2f03cda8-06aa-4b9e-961d-bf68a7a867a1",
"status": "NOTIFICATION_SENT"
}
},
"answer_version": 3
}
Response contains notification_info
object:
Field | Description | Type |
---|---|---|
notification_id | UUID of notification object | String |
status | notification status | String |
PC Inform 2.0 API
Create push sending task
endpoint: {{pc-pusher-host}}/pc-inform/api/notification
method: POST
Request Sample
{
"device_token": "72d4cc0ec709b2605914fe45e3605f2fc7735369e3d5e3fcdde14da9cdbaa9e6",
"device_type": "ios",
"time_to_live": 120,
"priority": "HIGH",
"collapse_key": "1222",
"payload": "VGVzdCBQQyBQdXNoZXI=",
"callback_url": "http://app.example.com/approve_delivery",
"payloader_url": "http://pusher.example.com/api/payload",
"message": { "aps": {
"alert": "There is notification",
"sound": "default",
"badge": 1,
"mutable-content": 1,
"category": "PUSH_CATCHER"
}
}
}
Response Sample
{
"uuid": "6229a35e-eb74-4341-94ec-fc6335346c03"
}
The request creates push-task
with optional payload
to be delivered and processed as shown in Workflow chapter.
Request params:
Field name | Mandatory | Description | Type |
---|---|---|---|
device_token | yes | Device push token | String |
time_to_live | no | time to live for cloud-service | Number |
priority | no | Priority cloud-service parameter (HIGH or NORMAL) | String |
collapse_key | no | Collapse key for cloud-service | String |
device_type | yes | Type of the device (iOS/apple, Android/google, Huawei) | String |
payload | no | base64 encoded payload |
Base64 String |
callback_url | no | url for status callbacks to an Application | String |
payloader_url | no | url of Payloader service to get push payload |
String |
message | yes | push notification with specific for cloud-service structure | JSON-Object |
Response object:
Field | Description | Type |
---|---|---|
uuid | UUID of notification object | String |
Get push task status
endpoint: {{pc-pusher-host}}/pc-inform/api/notification/{{notification_uuid}}
method: GET
Response sample
{
"uuid": "6229a35e-eb74-4341-94ec-fc6335346c03",
"status": "NOTIFICATION_SENT",
"push_type": "Apple",
"device_token": "72d4cc0ec709b2605914fe45e3605f2fc7735369e3d5e3fcdde14da9cdbaa9e6",
"callback_url": "http://app.example.com/approve_delivery",
"payloader_url": "http://pusher.example.com/api/payload",
"payload": "VGVzdCBQQyBQdXNoZXI="
}
The request is used to get notification status by uuid
.
Response:
Field | Description | Type |
---|---|---|
uuid | UUID of notification object | String |
status | Notification status | String |
push_type | Device type | String |
device_token | Push token of device | String |
callback_url | Callback url | String |
payloader_url | Payloader url | String |
payload | Push payload | Base64 String |
Payload request
endpoint: {{pc-pusher-host}}/pc-inform/api/payload
method: POST
Request sample
{
"auth_token": "4f84bc0f9fffc793aa6a2e6b010737c3a5294fd2853111bcef4728af486f8263",
"uuid": "6229a35e-eb74-4341-94ec-fc6335346c03"
}
Response sample
{
"uuid": "6229a35e-eb74-4341-94ec-fc6335346c03",
"payload": "VGVzdCBQQyBQdXNoZXI="
}
The request is used by mobile device to get push payload and to notify PC Pusher about delivery status.
E.g. if a mobile device has successfuly requested (with success authentication) payload, then push notification has been delivered.
To process the request a mobile device has to calculate authentication code
.
HMAC calculating example
For uuid
= c03a6d7f-5b5c-49af-be5c-6ea380080cb7 and device_token
= fu37vBAcNxY:APA91bGMpZIh7zcksU2cjNVE8ZRhFyo6Xxac-K8Gp3ZOgVkZdanH5xHHpGkaFN1o2khW86pkU2nrC4EUmSaxRKpAYCA9v5h3YtMm-KaWbMUNHn3IWdzn3lFQRFWOtzD9GTl2qlQMezYS
Hex-String for HMAC-SHA256(sha256(device_token), uuid)
will be: 4f84bc0f9fffc793aa6a2e6b010737c3a5294fd2853111bcef4728af486f8263
Request params:
Field | Description | Type |
---|---|---|
auth_token | authentication code | Hex-String |
uuid | Notification UUID | String |
Response contains following fields:
Field | Description | Type |
---|---|---|
uuid | UUID of notification object | String |
payload | Push payload | Base64 String |
Callback
Callback Sample
{
"task_uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx",
"status": 3
}
Callback will be sent by Callbacker
at the end of the workflow.
Callbacker
sends callbacks with current status in case of following statuses:
- NOTIFICATION_SENDING_ERROR
- PAYLOAD_SENT
With receiving the callback the Application can control push delivery status
Push Task Statuses
Status | Num value | Description |
---|---|---|
NEW | 0 | Notification has been created |
NOTIFICATION_SENT | 1 | Notification has been sent to cloud-service |
NOTIFICATION_SENDING_ERROR | 2 | An Error occured during notification sending |
PAYLOAD_SENT | 3 | Payload has been sent to a mobile device |
PAYLOAD_SENDING_ERROR | 4 | An Error occured during payload sending |
CALLBACK_DONE | 5 | Callback is done |
CALLBACK_ERROR | 6 | An Error occured during sending callback to an Application |
Configuration
Microservices configuration params
Variable | Description | Default |
---|---|---|
StompBrokerRelay | ||
server.port | Web server port for StompBrokerRelay | 8081 |
broker.host | Hostname of External message broker (Rabbit, Apache MQ, etc.) | localhost |
broker.username | Client login for STOMP-acceptor of message broker | guest |
broker.password | Client password for STOMP-acceptor of message broker | guest |
broker.destination.prefix | queue prefix for message broker | /queue |
broker.embedded.enabled | Enabling embedded in-memmory message broker or use external | true |
PushReceiver | ||
server.port | Web server port for PushReceiver | 8080 |
stomp.broker.relay.address | StompBrokerRelay address | localhost:8081 |
pusher.statistic.enabled | Enables statistic of sent pushes | false |
pusher.statistic.delay | Delay between statistic frames in msec | 300000 |
receiver.cache.pushsettings.capacity | push templates cache initial size | 100 |
receiver.cache.pushsettings.ttl | TTL for push templates cache in minutes | 1 |
receiver.stomp.reconnect.delay | Time between reconnect attempts to StompBrokerRelay in msec | 5000 |
spring.redis.host | Redis host | localhost |
spring.redis.port | Redis port | 49153 |
redis.ttl | TTL for Redis cache in days | 1 |
AndroidSender | ||
sender.config.proxy.host | proxy-server host for outgoing connections | null |
sender.config.proxy.port | proxy-server port for outgoing connections | 0 |
sender.config.proxy.username | proxy-server username | null |
sender.config.proxy.passsword | proxy-server password | null |
stomp.broker.relay.address | StompBrokerRelay address | localhost:8081 |
android.cache.credentials.capacity | credential settings cache initial size | 10 |
android.cache.credentials.ttl | TTL for credential settings cache in minutes | 1 |
android.poolexecutor.poolsize | Initial outgoing connections count | 10 |
android.poolexecutor.maxpoolsize | Max outgoing connections count | 30 |
android.stomp.reconnect.delay | Time between reconnect attempts to StompBrokerRelay in msec | 5000 |
AppleSender | ||
sender.config.proxy.host | proxy-server host for outgoing connections | null |
sender.config.proxy.port | proxy-server port for outgoing connections | 0 |
sender.config.proxy.username | proxy-server username | null |
sender.config.proxy.passsword | proxy-server password | null |
stomp.broker.relay.address | StompBrokerRelay address | localhost:8081 |
apple.cache.credentials.capacity | credential settings cache initial size | 10 |
apple.cache.credentials.ttl | TTL for credential settings cache in minutes | 1 |
apple.poolexecutor.poolsize | Initial outgoing connections count | 10 |
apple.poolexecutor.maxpoolsize | Max outgoing connections count | 30 |
apple.stomp.reconnect.delay | Time between reconnect attempts to StompBrokerRelay in msec | 5000 |
HuaweiSender | ||
sender.config.proxy.host | proxy-server host for outgoing connections | null |
sender.config.proxy.port | proxy-server port for outgoing connections | 0 |
sender.config.proxy.username | proxy-server username | null |
sender.config.proxy.passsword | proxy-server password | null |
stomp.broker.relay.address | StompBrokerRelay address | localhost:8081 |
huawei.cache.credentials.capacity | credential settings cache initial size | 10 |
huawei.cache.credentials.ttl | TTL for credential settings cache in minutes | 1 |
huawei.poolexecutor.poolsize | Initial outgoing connections count | 10 |
huawei.poolexecutor.maxpoolsize | Max outgoing connections count | 30 |
huawei.stomp.reconnect.delay | Time between reconnect attempts to StompBrokerRelay in msec | 5000 |
Payloader | ||
server.port | Web server port for Payloader | 8080 |
spring.redis.host | Redis host | localhost |
spring.redis.port | Redis port | 49153 |
redis.ttl | TTL for Redis cache in days | 1 |
stomp.broker.relay.address | StompBrokerRelay address | localhost:8081 |
payloader.stomp.reconnect.delay | Time between reconnect attempts to StompBrokerRelay in msec | 5000 |
Callbacker | ||
stomp.broker.relay.address | StompBrokerRelay address | localhost:8081 |
callbacker.stomp.reconnect.delay | Time between reconnect attempts to StompBrokerRelay in msec | 5000 |
callbacker.poolexecutor.poolsize | Initial outgoing connections count | 10 |
callbacker.poolexecutor.maxpoolsize | Max outgoing connections count | 30 |
Config directory
PC Pusher tries to find config files on following directories in provided order:
/opt/wildfly/pc_pusher
,/opt/pc/pc_pusher
,C:\pc\pc_pusher
,C:\wildfly\pc_pusher
In case config is found - directory with config will be path_to_config
Mobile Apps Credentials
Credentials for PC Pusher 5.2 API
Credential File Sample
{
"android": {
"google_api_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"ios": {
"apns_p8": {
"use_dev_gate": false,
"apns_key_id": "xxxxxxxxxxx",
"apns_team_id": "xxxxxxxxxx",
"apns_key": "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxx\nxxxxxxxxxxx\nxxxxxxxxxx\n-----END PRIVATE KEY-----"
}
},
"huawei": {
"client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"client_id": "xxxxxxxxx"
}
}
PC Pusher has to know cloud-services credentials to send push.
PC Pusher has built-in credentials to work with PayControl and PayConfirm mobile apps via PC Pusher 5.2 API.
Credentials are managed by AppleSender
, AndroidSender
and HuaweiSender
microservices.
To specify app credentials for you app, do the following:
- Create file with credentials:
{{app_id}}.json
, whereapp_id
is bundle-id/package-id of your mobile app - Fullfill credentials with structure like in the sample in code area
- Place credentials file to credentials config directory
{{path_to_config}}/apps/{{app_id}}.json
Credentials for PC Inform 2.0 API
Credential File Sample
{
"android": {
"google_api_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"ios": {
"apns_p8": {
"use_dev_gate": false,
"apns_key_id": "xxxxxxxxxxx",
"apns_team_id": "xxxxxxxxxx",
"apns_key": "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxx\nxxxxxxxxxxx\nxxxxxxxxxx\n-----END PRIVATE KEY-----",
"bundle":"**.********.**********"
}
},
"huawei": {
"client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"client_id": "xxxxxxxxx"
}
}
PC Inform 2.0 API doesn't specify mobile app id (bundle-id or package-id) to send push.
That's why in case you use PC Inform 2.0 API credentials has to comply following:
- credentials MUST be specified in
{{path_to_config}}/apps/defualt.json
- credentials MUST contain
ios.apns_p8.bundle
value, becuase of APNS requires to specify bundle-id to send push
Push Templates (for PC Pusher 5.2 API)
Templates File Sample
{
"android": {
"templates": {
"transaction": [
{
"to": "%DEVICE_TOKEN%",
"notification": {
"tag": "%USER_ID%",
"title": "There is new transaction to confirm",
"body": "You have non-confirmed transactions",
"icon": "paycontrol_push",
"sound": "default"
},
"data": {
"type": "PayControl_v2"
}
},
{
"to": "%DEVICE_TOKEN%",
"data": {
"type": "PayControl_v2",
"userid": "%USER_ID%",
"transactionid": "%TRANSACTION_ID%"
}
}
]
}
},
"ios": {
"templates": {
"ios_to_fcm" : false,
"transaction": [
{
"aps": {
"alert": "There is new transaction to confirm",
"sound": "default",
"badge": 1,
"mutable-content": 1,
"category": "NEW_OPERATION"
},
"type": "PayControl",
"userid": "%USER_ID%",
"transactionid": "%TRANSACTION_ID%",
"pc_notification_type": "alert",
"pc_notification_priority": 10,
"pc_notification_timeout": 600,
"pc_collapse_id": "%USER_ID%"
}
]
}
},
"huawei": {
"templates": {
"transaction": [
{
"validate_only": false,
"message": {
"android": {
"notification": {
"tag": "%USER_ID%",
"title": "There is new transaction to confirm",
"body": "You have non-confirmed transactions",
"icon": "paycontrol_push",
"click_action": {
"type": 3
}
}
},
"token": [
"%DEVICE_TOKEN%"
]
}
},
{
"validate_only": false,
"message": {
"android": {
"collapse_key": -1,
"urgency": "HIGH",
"ttl": "86400",
"data": "{\"type\": \"PayControl_v2\",\n\"userid\": \"%USER_ID%\",\"transactionid\": \"%TRANSACTION_ID%\"}"
},
"token": [
"%DEVICE_TOKEN%"
]
}
}
]
}
}
}
PC Pusher has built-in push templates to work with PayControl and PayConfirm mobile apps (version 5.x).
In case you use PC Pusher API, you can configure your own push templates and credentials.
Templates are managed by PushReceiver
microservice.
To use your own push templates, do the following:
- Create file with templates:
{{system_id}}.json
, wheresystem_id
is PC Server system-id (specified in send-push-request) - Fullfill push templates with structure like the in sample in code area
- Place templates file to templates config directory
{{path_to_config}}/systems/{{system_id}}.json