@@ -8,6 +8,7 @@ import { randomString } from './PushAdapterUtils';
88
99const LOG_PREFIX = 'parse-server-push-adapter FCM' ;
1010const FCMRegistrationTokensMax = 500 ;
11+ const FCMTimeToLiveMax = 4 * 7 * 24 * 60 * 60 ; // FCM allows a max of 4 weeks
1112
1213export default function FCM ( args ) {
1314 if ( typeof args !== 'object' || ! args . firebaseServiceAccount ) {
@@ -40,7 +41,6 @@ FCM.prototype.send = function(data, devices) {
4041 return ;
4142 }
4243
43-
4444 // We can only have 500 recepients per send, so we need to slice devices to
4545 // chunk if necessary
4646 const slices = sliceDevices ( devices , FCM . FCMRegistrationTokensMax ) ;
@@ -60,7 +60,7 @@ FCM.prototype.send = function(data, devices) {
6060 const length = deviceTokens . length ;
6161 log . info ( LOG_PREFIX , `sending push to ${ length } devices` ) ;
6262
63- return this . sender . sendEachForMulticast ( fcmPayload . payload . data )
63+ return this . sender . sendEachForMulticast ( fcmPayload . data )
6464 . then ( ( response ) => {
6565 const promises = [ ] ;
6666 const failedTokens = [ ] ;
@@ -101,21 +101,59 @@ FCM.prototype.send = function(data, devices) {
101101 * Generate the fcm payload from the data we get from api request.
102102 * @param {Object } requestData The request body
103103 * @param {String } pushId A random string
104- * @param {Number } timeStamp A number whose format is the Unix Epoch
104+ * @param {Number } timeStamp A number in milliseconds since the Unix Epoch
105105 * @returns {Object } A payload for FCM
106106 */
107107function generateFCMPayload ( requestData , pushId , timeStamp , deviceTokens ) {
108108 delete requestData [ 'where' ] ;
109- requestData . tokens = deviceTokens ;
110- const payload = { }
111109
112- payload . payload = {
113- data : requestData ,
114- push_id : pushId ,
115- time : new Date ( timeStamp ) . toISOString ( )
110+ const payloadToUse = {
111+ data : { } ,
112+ push_id : pushId ,
113+ time : new Date ( timeStamp ) . toISOString ( )
114+ } ;
115+
116+ // Use rawPayload instead of the GCM implementation if it exists
117+ if ( requestData . hasOwnProperty ( 'rawPayload' ) ) {
118+ payloadToUse . data = {
119+ ...requestData . rawPayload ,
120+ tokens : deviceTokens
121+ } ;
122+ } else {
123+ // Android payload according to GCM implementation
124+ const androidPayload = {
125+ android : {
126+ priority : 'high'
127+ } ,
128+ tokens : deviceTokens
129+ } ;
130+
131+ if ( requestData . hasOwnProperty ( 'notification' ) ) {
132+ androidPayload . notification = requestData . notification ;
133+ }
134+
135+ if ( requestData . hasOwnProperty ( 'data' ) ) {
136+ androidPayload . data = requestData . data ;
137+ }
138+
139+ if ( requestData [ 'expiration_time' ] ) {
140+ const expirationTime = requestData [ 'expiration_time' ] ;
141+ // Convert to seconds
142+ let timeToLive = Math . floor ( ( expirationTime - timeStamp ) / 1000 ) ;
143+ if ( timeToLive < 0 ) {
144+ timeToLive = 0 ;
145+ }
146+ if ( timeToLive >= FCMTimeToLiveMax ) {
147+ timeToLive = FCMTimeToLiveMax ;
148+ }
149+
150+ androidPayload . android . ttl = timeToLive ;
151+ }
152+
153+ payloadToUse . data = androidPayload ;
116154 }
117155
118- return payload ;
156+ return payloadToUse ;
119157}
120158
121159/**
@@ -132,7 +170,6 @@ function sliceDevices(devices, chunkSize) {
132170 return chunkDevices ;
133171}
134172
135-
136173/**
137174 * Creates an errorPromise for return.
138175 *
0 commit comments