我正在尝试使用主题发送多个Web通知,而不是向每个令牌发送通知。
,但我坚持使用 401 unauthorized
这是我的代码
首先,我请求Web浏览器权限通过此Firebase示例代码通知令牌:https://github.com/firebase/quickstart-js/blob/master/master/messaging
在 index.html
上,i更改这样的代码以将令牌发送到服务器以订阅主题
function resetUI() {
clearMessages();
// [START get_token]
// Get Instance ID token. Initially this makes a network call, once retrieved
// subsequent calls to getToken will return from cache.
messaging.getToken().then(function (currentToken) {
if (currentToken) {
console.log("Get Token OK: " + currentToken);
sendTokenToServer(currentToken);
} else {
// Show permission request.
console.log('No Instance ID token available. Request permission to generate one.');
// Reset Token on Server to False
setTokenSentToServer(false);
// Request permission for Token
requestPermission();
}
}).catch(function (err) {
console.log('An error occurred while retrieving token. ', err);
setTokenSentToServer(false);
});
// [END get_token]
}
// Send the Instance ID token your application server, so that it can:
// - send messages back to this app
// - subscribe/unsubscribe the token from topics
function sendTokenToServer(currentToken) {
if (!(window.localStorage.getItem('EDXNotificationIsSentToServer') === '1')) {
console.log('Sending token to server...');
var tokenObject = {
token: currentToken
};
$.ajax({
type: "POST",
url: '@Url.Action("SaveToken", "Api")',
data: JSON.stringify(tokenObject),
contentType: "application/json; charset=utf-8",
success: function (data) {
if (data) {
// TODO(developer): Send the current token to your server.
setTokenSentToServer(true);
}
},
complete: function (status) {
},
error: function (error) { }
});
} else {
console.log('Token already sent to server so won't send it again unless it changes');
}
}
在服务器上,我将令牌存储到数据库中并订阅以测试主题
public class ApiController : Controller
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Lưu token
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public JsonResult SaveToken(TBL_Customer_Tokens model)
{
try
{
if (!string.IsNullOrEmpty(model.token))
{
bool ret = true;
if(GCMUtils.SubcribeTokenToTopic(model.token, ConfigurationManager.AppSettings["GCMTopic"]))
ret = DataServiceFactory.GetCustomerService().SaveToken(model.token); // Save token to database, don't care about this function. It is ok
if (ret)
Json(true, JsonRequestBehavior.AllowGet);
}
}
catch (Exception ex)
{
log.Debug(ex.Message, ex);
}
return Json(false, JsonRequestBehavior.AllowGet);
}
}
这是gcmutils
public class GCMUtils
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static bool SubcribeTokenToTopic(string token, string topic)
{
try
{
string url = String.Format("https://iid.googleapis.com/iid/v1/{0}/rel/topics/{1}", token, topic);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.ContentType = "application/json";
req.Headers.Add("Authorization", "key=" + ConfigurationManager.AppSettings["GCMServerKey"]);
req.Method = "POST";
req.ContentLength = 0;
Stream reqStream = req.GetRequestStream();
reqStream.Close();
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
return true;
}
catch (Exception ex)
{
log.Debug(ex.Message, ex);
}
return false;
}
}
检索令牌,保存到数据库并成功订阅了主题。因此,您可以忽略上面的代码,仅分析问题belows
其次,我正在尝试将网络通知发送到主题,而不是向每个令牌发送单个通知
public static bool SendFirebaseTopicNotificationAsync(string topicSubscription, NotificationPayload dat)
{
try
{
List<string> scopes = new List<string>();
scopes.Add("https://www.googleapis.com/auth/firebase");
scopes.Add("https://www.googleapis.com/auth/firebase.messaging");
string accesstoken = GoogleCredential.FromFile(ConfigurationManager.AppSettings["GoogleCredentialFilePath"])
.CreateScoped(scopes)
.UnderlyingCredential
.GetAccessTokenForRequestAsync().Result;
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/v1/projects/test-project/messages:send");
tRequest.Method = "post";
tRequest.Headers.Add("Authorization", "bearer " + accesstoken);
tRequest.ContentType = "application/json";
var payload = new
{
message = new
{
topic = topicSubscription,
notification = new {
title = dat.title,
body = dat.body
},
webpush = new
{
fcm_options = new {
link = dat.click_action
}
}
}
};
string postbody = JsonConvert.SerializeObject(payload).ToString();
Byte[] byteArray = Encoding.UTF8.GetBytes(postbody);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
if (dataStreamResponse != null) using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
Console.WriteLine(sResponseFromServer);
return true;
}
}
}
}
}
catch (Exception ex)
{
log.Debug(ex.Message, ex);
}
return false;
}
请注意,SendFirebaseTopicNotificationAsync
中的test-project
是项目名称。我确定这是真的
ConfigurationManager.AppSettings["GoogleCredentialFilePath"]
是通往.json密钥文件的绝对文件路径form-json-or-p12-key-in-c-sharp/
,但我得到401 Unauthorized
错误。GoogleCredential
的访问令牌似乎是错误的
任何帮助将不胜感激
谢谢
愚蠢的错误这是这行
tRequest.Headers.Add("Authorization", "bearer " + accesstoken);
bearer
是错误的,使用 Bearer
而不是
tRequest.Headers.Add("Authorization", "Bearer " + accesstoken);
我还找到了这篇文章https://github.com/googleapis/google-api-dotnet-client/issues/1140
这个家伙也有401 Unauthorized
。但是他的问题与我不同。他在Google Cloud Platform https://console.cloud.google.com/apis/dashboard