由于FCM的所有npm模块似乎仍然使用旧版HTTP API,因此我尝试通过节点上的最新HTTP v1 API实现FCM消息传递。
虽然docs引用Google Client API,但要求它似乎有点过分,因为我只需要JWT oAuth2Client,它是Google Auth Library的一部分。
到目前为止我提出的模块:
var request = require('request');
var googleAuth = require('google-auth-library');
module.exports.Sender = function(projectId, key) {
var _projectId = projectId;
var _key = key;
var _tokens = {};
var _jwtClient = new googleAuth.JWT(
key.client_email,
null,
key.private_key,
['https://www.googleapis.com/auth/firebase.messaging'],
null
);
var _getAccessToken = function() {
return new Promise(function(resolve, reject) {
_jwtClient.authorize(function(error, tokens) {
if (error) {
reject(error);
return;
}
_tokens = tokens;
resolve(tokens.access_token);
});
});
};
var _sendMessage = function(message) {
return new Promise(function(resolve, reject) {
request({
method: 'POST',
url: 'https://fcm.googleapis.com/v1/projects/' + _projectId + '/messages:send',
headers: {
'Content-type': 'application/json',
'Authorization': 'Bearer ' + _tokens.access_token
},
body: message,
json: true
}, function(error, response, body) {
if(error) reject(error);
else {
resolve(response);
}
});
});
};
return {
getAccessToken: _getAccessToken,
sendMessage: _sendMessage
}
}
至于使用它:
var fcm = require('./index.js');
var projectId = 'someProjectId';
var key = require('./someServiceAccount.json');
var sender = new fcm.Sender(projectId, key);
var message = {
validate_only: false,
message: {
token: 'someDeviceToken',
android: {
collapse_key: 'someCollapseKey',
priority: 'HIGH',
restricted_package_name: 'com.some.domain',
data: {
title: 'someTitle',
body: 'someBody',
sound: 'default',
action: 'someAction'
}
},
apns: {
headers: {
'apns-priority': '10'
},
payload: {
aps: {
alert: {
title: 'someTitle',
body: 'someBody'
},
sound: 'default',
badge: 2
},
action: 'someAction'
}
}
}
};
sender.getAccessToken() //TODO: should be done once in sender
.then(function(accessToken) {
return sender.sendMessage(message);
})
.then(function(response) {
console.log(response.body);
})
.catch(function(error) {
console.log(error);
});
一切都很好,花花公子;我正在使用cordova-plugin-firebase在我的设备上收到通知。
API调用使用oAuth2进行身份验证,其中需要刷新访问令牌(似乎是1小时)。文档声明:
请注意,刷新令牌的调用是幂等的。在你之后 令牌到期时,自动调用令牌刷新方法 检索更新的令牌。
我似乎无法弄清楚这是如何实现的。 JWT授权调用只留下一个将访问令牌作为字符串保存的通用对象。当JWT客户端扩展oAuth2Client时,我浏览了它的源代码,似乎有一个request method自动刷新访问令牌。
JWT.authorize返回的对象的refresh_token也似乎总是“jwt-placeholder”。
离开我的问题:
如何获得有效的刷新令牌?
我可以通过JWT客户端使用oAuth2Client方法,因为它不会使用任何前端交互(generateAuthUrl)
使用请求方法会阻止我的代码吗?
我需要某种消息队列吗?
在我继续研究和编码的同时,我想知道是否有人可以在此期间给我一些指示或有用的文档。
答案 0 :(得分:0)
我实际上是使用请求方法来使用它。这也消除了对请求模块的需要。如果我理解正确,oAuth2Client应该自动刷新访问令牌,并在请求失败时进行单次重试。
我更新的发件人模块:
var googleAuth = require('google-auth-library');
module.exports.Sender = function(projectId, key) {
var _projectId = projectId;
var _jwtClient = new googleAuth.JWT(
key.client_email,
null,
key.private_key,
['https://www.googleapis.com/auth/firebase.messaging'],
null
);
var _init = function() {
return new Promise(function(resolve, reject) {
_jwtClient.authorize(function(error, tokens) {
if (error) {
reject(error);
return;
}
resolve();
});
});
};
var _sendMessage = function(message) {
return _jwtClient.request({
method: 'post',
url: 'https://fcm.googleapis.com/v1/projects/' + _projectId + '/messages:send',
data: message
});
}
return {
init: _init,
sendMessage: _sendMessage
}
}
和用法:
sender.init()
.then(function(accessToken) {
return sender.sendMessage(message);
})
.then(function(response) {
console.log(response.data);
})
.catch(function(error) {
console.log(error);
});
仍然存在关于refresh_token的问题,作为JWT客户端overrides it。如何正确实施?