Update apnsservice to parse template in APN compatible way
This commit is contained in:
Родитель
bbdd7858fb
Коммит
4d8aeab574
|
@ -49,11 +49,12 @@ function ApnsService(notificationHubService) {
|
|||
* If null it will broadcast to all registrations in this hub
|
||||
* @param {object|string} payload The message's JSON payload as specified below.
|
||||
* If the payload is a string, follow the APNS format as in https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [payload.badge] The number to display over the app icon.
|
||||
* @param {string} [payload.alert] The alert text.
|
||||
* @param {string} [payload.sound] The sound file name.
|
||||
* @param {object} [payload.payload] The payload object that contains the notification text.
|
||||
* @param {date} [payload.expiry] The expiration date. (in W3C DTF, YYYY-MM-DDThh:mmTZD (e.g. 1997-07-16T19:20+01:00))
|
||||
* @param {object} [payload.aps] If the 'aps' member is provided, the object is delivered to APNS as-is after expiry is processed. The object is assumed to follow the APNS format at https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [payload.badge] If the 'aps' member is not provided, the number to display over the app icon.
|
||||
* @param {string} [payload.alert] If the 'aps' member is not provided, the alert text.
|
||||
* @param {string} [payload.sound] If the 'aps' member is not provided, the sound file name.
|
||||
* @param {object} [payload.payload] If the 'aps' member is not provided, the payload object that contains the notification text.
|
||||
* @param {Function(error, response)} callback `error` will contain information
|
||||
* if an error occurs; otherwise, `response`
|
||||
* will contain information related to this operation.
|
||||
|
@ -89,28 +90,16 @@ ApnsService.prototype.send = function (tags, payload, callback) {
|
|||
headers[HeaderConstants.SERVICE_BUS_NOTIFICATION_TAGS] = tags;
|
||||
}
|
||||
|
||||
payload = _.clone(payload);
|
||||
|
||||
if (payload.expiry) {
|
||||
var expiry = new Date(payload.expiry);
|
||||
headers[HeaderConstants.SERVICE_BUS_NOTIFICATION_APNS_EXPIRY] = expiry.toISOString();
|
||||
delete payload.expiry;
|
||||
}
|
||||
|
||||
if (!_.isString(payload)) {
|
||||
if (!payload.aps) {
|
||||
payload = { aps: payload };
|
||||
payload = _.clone(payload);
|
||||
|
||||
if (payload.aps.payload) {
|
||||
Object.keys(payload.aps.payload).forEach(function (innerPayloadMember) {
|
||||
payload[innerPayloadMember] = payload.aps.payload[innerPayloadMember];
|
||||
});
|
||||
|
||||
delete payload.aps.payload;
|
||||
}
|
||||
if (payload.expiry) {
|
||||
var expiry = new Date(payload.expiry);
|
||||
headers[HeaderConstants.SERVICE_BUS_NOTIFICATION_APNS_EXPIRY] = expiry.toISOString();
|
||||
delete payload.expiry;
|
||||
}
|
||||
|
||||
payload = JSON.stringify(payload);
|
||||
payload = this._formatPayload(payload);
|
||||
}
|
||||
|
||||
headers[HeaderConstants.CONTENT_TYPE] = 'application/json;charset="utf-8"';
|
||||
|
@ -176,11 +165,12 @@ ApnsService.prototype.createOrUpdateNativeRegistration = function (registrationI
|
|||
* @param {string|array} tags The tags.
|
||||
* @param {object|string} template The message's JSON payload as specified below.
|
||||
* If the payload is a string, follow the APNS format as in https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [template.badge] The number to display over the app icon.
|
||||
* @param {string} [template.alert] The alert text.
|
||||
* @param {string} [template.sound] The sound file name.
|
||||
* @param {object} [template.payload] The payload object that contains the notification text.
|
||||
* @param {date} [template.expiry] The expiration date.
|
||||
* @param {object} [template.aps] If the 'aps' member is provided, the registration is delivered to NotifcationHub as-is after expiry is processed. The object is assumed to follow the APNS format at https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [template.badge] If the 'aps' member is not provided, the number to display over the app icon.
|
||||
* @param {string} [template.alert] If the 'aps' member is not provided, the alert text.
|
||||
* @param {string} [template.sound] If the 'aps' member is not provided, the sound file name.
|
||||
* @param {object} [template.payload] If the 'aps' member is not provided, the payload object that contains the notification text.
|
||||
* @param {object} [options] The request options.
|
||||
* @param {Function(error, response)} callback `error` will contain information
|
||||
* if an error occurs; otherwise, `response`
|
||||
|
@ -212,11 +202,12 @@ ApnsService.prototype.createTemplateRegistration = function (token, tags, templa
|
|||
* @param {string} token The device token.
|
||||
* @param {object|string} template The message's JSON payload as specified below.
|
||||
* If the payload is a string, follow the APNS format as in https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [template.badge] The number to display over the app icon.
|
||||
* @param {string} [template.alert] The alert text.
|
||||
* @param {string} [template.sound] The sound file name.
|
||||
* @param {object} [template.payload] The payload object that contains the notification text.
|
||||
* @param {date} [template.expiry] The expiration date.
|
||||
* @param {object} [template.aps] If the 'aps' member is provided, the registration is delivered to NotifcationHub as-is after expiry is processed. The object is assumed to follow the APNS format at https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [template.badge] If the 'aps' member is not provided, the number to display over the app icon.
|
||||
* @param {string} [template.alert] If the 'aps' member is not provided, the alert text.
|
||||
* @param {string} [template.sound] If the 'aps' member is not provided, the sound file name.
|
||||
* @param {object} [template.payload] If the 'aps' member is not provided, the payload object that contains the notification text.
|
||||
* @param {object} [options] The request options.
|
||||
* @param {Function(error, response)} callback `error` will contain information
|
||||
* if an error occurs; otherwise, `response`
|
||||
|
@ -249,11 +240,12 @@ ApnsService.prototype.createOrUpdateTemplateRegistration = function (registratio
|
|||
* @param {string} token The device token.
|
||||
* @param {object|string} template The message's JSON payload as specified below.
|
||||
* If the payload is a string, follow the APNS format as in https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [template.badge] The number to display over the app icon.
|
||||
* @param {string} [template.alert] The alert text.
|
||||
* @param {string} [template.sound] The sound file name.
|
||||
* @param {object} [template.payload] The payload object that contains the notification text.
|
||||
* @param {date} [template.expiry] The expiration date.
|
||||
* @param {object} [template.aps] If the 'aps' member is provided, the registration is delivered to NotifcationHub as-is after expiry is processed. The object is assumed to follow the APNS format at https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
|
||||
* @param {number} [template.badge] If the 'aps' member is not provided, the number to display over the app icon.
|
||||
* @param {string} [template.alert] If the 'aps' member is not provided, the alert text.
|
||||
* @param {string} [template.sound] If the 'aps' member is not provided, the sound file name.
|
||||
* @param {object} [template.payload] If the 'aps' member is not provided, the payload object that contains the notification text.
|
||||
* @param {object} [options] The request options.
|
||||
* @param {Function(error, response)} callback `error` will contain information
|
||||
* if an error occurs; otherwise, `response`
|
||||
|
@ -359,33 +351,22 @@ ApnsService.prototype._createBody = function (elementName, token, tags, template
|
|||
|
||||
if (template) {
|
||||
var payload = _.clone(template);
|
||||
|
||||
if (payload.payload) {
|
||||
Object.keys(payload.payload).forEach(function (property) {
|
||||
payload[property] = payload.payload[property];
|
||||
});
|
||||
|
||||
delete payload.payload;
|
||||
}
|
||||
var expiry;
|
||||
|
||||
if (!_.isString(payload)) {
|
||||
var expiry;
|
||||
if (payload.expiry) {
|
||||
expiry = payload.expiry;
|
||||
delete payload.expiry;
|
||||
}
|
||||
|
||||
if (!payload.aps) {
|
||||
payload = { aps: payload };
|
||||
}
|
||||
|
||||
payload = JSON.stringify(payload);
|
||||
|
||||
registration.BodyTemplate = '<![CDATA[' + payload + ']]>';
|
||||
|
||||
if (expiry) {
|
||||
registration['Expiry'] = expiry;
|
||||
}
|
||||
payload = this._formatPayload(payload);
|
||||
}
|
||||
|
||||
registration.BodyTemplate = '<![CDATA[' + payload + ']]>';
|
||||
|
||||
// Expiry member must be set after BodyTemplate
|
||||
if (expiry) {
|
||||
registration.Expiry = expiry;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,4 +387,20 @@ ApnsService.prototype._createTemplateBody = function (token, tags, template, opt
|
|||
return this._createBody('AppleTemplateRegistrationDescription', token, tags, template, options);
|
||||
};
|
||||
|
||||
module.exports = ApnsService;
|
||||
ApnsService.prototype._formatPayload = function (payload) {
|
||||
if (!payload.aps) {
|
||||
payload = { aps: payload };
|
||||
|
||||
if (payload.aps.payload) {
|
||||
Object.keys(payload.aps.payload).forEach(function (innerPayloadMember) {
|
||||
payload[innerPayloadMember] = payload.aps.payload[innerPayloadMember];
|
||||
});
|
||||
|
||||
delete payload.aps.payload;
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify(payload);
|
||||
};
|
||||
|
||||
module.exports = ApnsService;
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -57,12 +57,13 @@ describe('APNS notifications registrations', function () {
|
|||
beforeEach(function (done) {
|
||||
suiteUtil.setupTest(function () {
|
||||
service.listNotificationHubs(function (err, hubs) {
|
||||
should.not.exist(err);
|
||||
var xplatHubs = hubs.filter(function (hub) {
|
||||
return hub.NotificationHubName.substr(0, hubNamePrefix.length) === hubNamePrefix;
|
||||
});
|
||||
|
||||
_.each(xplatHubs, function (hub) {
|
||||
service.deleteNotificationHub(hub.NotificationHubName, function () {});
|
||||
service.deleteNotificationHub(hub.NotificationHubName, function () { });
|
||||
});
|
||||
|
||||
done();
|
||||
|
@ -73,7 +74,7 @@ describe('APNS notifications registrations', function () {
|
|||
afterEach(function (done) {
|
||||
// Schedule deleting notification hubs
|
||||
_.each(hubNames, function (notificationHub) {
|
||||
service.deleteNotificationHub(notificationHub, function () {});
|
||||
service.deleteNotificationHub(notificationHub, function () { });
|
||||
});
|
||||
|
||||
suiteUtil.baseTeardownTest(done);
|
||||
|
@ -90,12 +91,12 @@ describe('APNS notifications registrations', function () {
|
|||
|
||||
suiteUtil.setupService(notificationHubService);
|
||||
service.createNotificationHub(hubName, {
|
||||
apns: {
|
||||
ApnsCertificate: process.env.AZURE_APNS_CERTIFICATE,
|
||||
CertificateKey: process.env.AZURE_APNS_CERTIFICATE_KEY,
|
||||
Endpoint: 'pushtestservice2.cloudapp.net'
|
||||
}
|
||||
}, done);
|
||||
apns: {
|
||||
ApnsCertificate: process.env.AZURE_APNS_CERTIFICATE,
|
||||
CertificateKey: process.env.AZURE_APNS_CERTIFICATE_KEY,
|
||||
Endpoint: 'pushtestservice2.cloudapp.net'
|
||||
}
|
||||
}, done);
|
||||
});
|
||||
|
||||
describe('native', function () {
|
||||
|
@ -118,7 +119,7 @@ describe('APNS notifications registrations', function () {
|
|||
|
||||
describe('list', function () {
|
||||
beforeEach(function (done) {
|
||||
notificationHubService.apns.createNativeRegistration(tokenId, [ 'mytag'], done);
|
||||
notificationHubService.apns.createNativeRegistration(tokenId, ['mytag'], done);
|
||||
});
|
||||
|
||||
it('should work without filtering', function (done) {
|
||||
|
@ -172,6 +173,7 @@ describe('APNS notifications registrations', function () {
|
|||
});
|
||||
|
||||
it('should work', function (done) {
|
||||
var executeSpy = sandbox.spy(notificationHubService, '_executeRequest');
|
||||
notificationHubService.apns.createTemplateRegistration(
|
||||
tokenId,
|
||||
null,
|
||||
|
@ -182,11 +184,14 @@ describe('APNS notifications registrations', function () {
|
|||
should.not.exist(error);
|
||||
registrationId = registration.RegistrationId;
|
||||
|
||||
executeSpy.args[0][1].should.include('<BodyTemplate><![CDATA[{"aps":{"alert":"$(alertMessage1)"}}]]></BodyTemplate>');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should work when payload matches APNS specs', function (done) {
|
||||
var executeSpy = sandbox.spy(notificationHubService, '_executeRequest');
|
||||
notificationHubService.apns.createTemplateRegistration(
|
||||
tokenId,
|
||||
null,
|
||||
|
@ -199,15 +204,40 @@ describe('APNS notifications registrations', function () {
|
|||
should.not.exist(error);
|
||||
registrationId = registration.RegistrationId;
|
||||
|
||||
executeSpy.args[0][1].should.include('<BodyTemplate><![CDATA[{"aps":{"alert":"$(alertMessage1)"}}]]></BodyTemplate>');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should work when payload matches APNS specs and has extra data', function (done) {
|
||||
var executeSpy = sandbox.spy(notificationHubService, '_executeRequest');
|
||||
notificationHubService.apns.createTemplateRegistration(
|
||||
tokenId,
|
||||
null,
|
||||
{
|
||||
aps: {
|
||||
alert: '$(alertMessage1)'
|
||||
},
|
||||
extraData: '$(data)'
|
||||
},
|
||||
function (error, registration) {
|
||||
should.not.exist(error);
|
||||
registrationId = registration.RegistrationId;
|
||||
|
||||
executeSpy.args[0][1].should.include('<BodyTemplate><![CDATA[{"aps":{"alert":"$(alertMessage1)"},"extraData":"$(data)"}]]></BodyTemplate>');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('update alert', function () {
|
||||
var registrationId;
|
||||
var executeSpy;
|
||||
|
||||
beforeEach(function (done) {
|
||||
executeSpy = sandbox.spy(notificationHubService, '_executeRequest');
|
||||
notificationHubService.apns.createTemplateRegistration(
|
||||
tokenId,
|
||||
null,
|
||||
|
@ -218,6 +248,8 @@ describe('APNS notifications registrations', function () {
|
|||
should.not.exist(error);
|
||||
registrationId = registration.RegistrationId;
|
||||
|
||||
executeSpy.args[0][1].should.include('<BodyTemplate><![CDATA[{"aps":{"alert":"$(alertMessage1)"}}]]></BodyTemplate>');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -227,6 +259,8 @@ describe('APNS notifications registrations', function () {
|
|||
});
|
||||
|
||||
it('should work', function (done) {
|
||||
sandbox.restore();
|
||||
executeSpy = sandbox.spy(notificationHubService, '_executeRequest');
|
||||
notificationHubService.apns.updateTemplateRegistration(
|
||||
registrationId,
|
||||
tokenId,
|
||||
|
@ -237,6 +271,54 @@ describe('APNS notifications registrations', function () {
|
|||
function (error) {
|
||||
should.not.exist(error);
|
||||
|
||||
executeSpy.args[0][1].should.include('<BodyTemplate><![CDATA[{"aps":{"alert":"$(newAlertMessage1)"}}]]></BodyTemplate>');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should work when payload member exists', function (done) {
|
||||
sandbox.restore();
|
||||
executeSpy = sandbox.spy(notificationHubService, '_executeRequest');
|
||||
notificationHubService.apns.updateTemplateRegistration(
|
||||
registrationId,
|
||||
tokenId,
|
||||
null,
|
||||
{
|
||||
alert: '$(newAlertMessage1)',
|
||||
payload: {
|
||||
data1: '$(data1)',
|
||||
data2: '$(data2)',
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
should.not.exist(error);
|
||||
|
||||
executeSpy.args[0][1].should.include('<BodyTemplate><![CDATA[{"aps":{"alert":"$(newAlertMessage1)"},"data1":"$(data1)","data2":"$(data2)"}]]></BodyTemplate>');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should work when aps exists without modifying payload as extra data', function (done) {
|
||||
sandbox.restore();
|
||||
executeSpy = sandbox.spy(notificationHubService, '_executeRequest');
|
||||
notificationHubService.apns.updateTemplateRegistration(
|
||||
registrationId,
|
||||
tokenId,
|
||||
null,
|
||||
{
|
||||
aps: { alert: '$(newAlertMessage1)' },
|
||||
payload: {
|
||||
data1: '$(data1)',
|
||||
data2: '$(data2)',
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
should.not.exist(error);
|
||||
|
||||
executeSpy.args[0][1].should.include('<BodyTemplate><![CDATA[{"aps":{"alert":"$(newAlertMessage1)"},"payload":{"data1":"$(data1)","data2":"$(data2)"}}]]></BodyTemplate>');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче