FCM授权总是失败
FCM Authorization always fails
今天我想从 GCM 切换到 FCM,所以我设置了所需的一切并希望实现服务器端代码。我使用了 gcm4j 库并将其更改为地址为 https://fcm.googleapis.com/fcm/send
。
所以我正在做以下事情:
FCM fcm = new FCMDefault(new FCMConfig().withKey(FCMGlobals.FCM_API_KEY));
FCMRequest request = new FCMRequest().withRegistrationId(android.getRegistration())
// .withCollapseKey(collapseKey)
.withDelayWhileIdle(true)
.withDataItem(FCMGlobals.FCM_PARAM_CODE, code)
.withDataItem(FCMGlobals.FCM_PARAM_USER_ID, "" + user.getId())
.withDataItem(FCMGlobals.FCM_PARAM_ADDITION, "" + addition);
ListenableFuture<FCMResponse> responseFuture = fcm.send(request);
Futures.addCallback(responseFuture, new FutureCallback<FCMResponse>() {
public void onFailure(Throwable t) {
log.error(t);
}
@Override
public void onSuccess(FCMResponse response) {
log.info(response.toString());
}
});
其实现是:
protected FCMResponse executeRequest(FCMRequest request) throws IOException {
byte[] content = this.objectMapper.writeValueAsBytes(request);
HttpURLConnection conn = this.connectionFactory.open(this.fcmUrl);
conn.setRequestMethod("POST");
conn.addRequestProperty("Authorization", getAuthorization(request));
conn.addRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setFixedLengthStreamingMode(content.length);
LoggerFactory.getLogger("FCMDefaultAbstract").info("Authorization: " + conn.getRequestProperty("Authorization"));
LoggerFactory.getLogger("FCMDefaultAbstract").info("Content-Type: " + conn.getRequestProperty("Content-Type"));
LoggerFactory.getLogger("FCMDefaultAbstract").info("send: " + new String(content));
try (OutputStream outputStream = conn.getOutputStream()) {
IOUtils.write(content, outputStream);
} catch (Exception e) {
throw new FCMNetworkException("Error sending HTTP request to FCM", e);
}
FCMResponse response;
try (InputStream inputStream = conn.getInputStream()) {
response = this.objectMapper.readValue(IOUtils.toByteArray(inputStream), FCMResponse.class);
} catch (IOException e) {
try (InputStream inputStreamError = conn.getErrorStream()) {
String str = inputStreamError != null ? IOUtils.toString(inputStreamError) : "No error details provided";
int responseCode = conn.getResponseCode();
if (responseCode < 500) {
throw new FCMNetworkException(conn.getResponseCode(), str.trim(), e);
} else {
throw new FCMNetworkException(conn.getResponseCode(), str.trim(), checkForRetryInResponse(conn), e);
}
}
}
response.setRequest(request);
response.setRetryAfter(checkForRetryInResponse(conn));
Iterator<String> iteratorId = request.getRegistrationIds().iterator();
Iterator<FCMResult> iteratorResponse = response.getResults().iterator();
while (iteratorId.hasNext() && iteratorResponse.hasNext()) {
iteratorResponse.next().setRequestedRegistrationId(iteratorId.next());
}
if (iteratorId.hasNext()) {
LOG.warn("Protocol error: Less results than requested registation IDs");
}
if (iteratorResponse.hasNext()) {
LOG.warn("Protocol error: More results than requested registation IDs");
}
return response;
}
这里是日志输出:
FCMDefaultAbstract Authorization: null
FCMDefaultAbstract Content-Type:application/json
FCMDefaultAbstract send: {"registration_ids":["dMpvzp*************************************2lRsSl_5lFET2"],"data":{"CODE":"201","USER_ID":"1","ADDITION":"1468083549493"},"delay_while_idle":true}
FCM FCMNetworkException: HTTP 401: No error details provided
Authorization
header 实际上不为空。它已使用我的 FCM API 密钥正确设置。如果有人试图访问 Authorization
密钥,只有 HTTPUrlConnection
实现会说 return null。
如您所见,我无法连接 FCM。代码 401
表示身份验证失败。
这可能是什么问题?
检查您使用的是 server type
API-KEY,而不是 client
或 browser
API-KEY。
如果您使用的是 Firebase,您可以在
中找到 API-KEY
项目设置 > 云消息
如果您正在使用云控制台,或者您不确定您使用的是哪个密钥,
您可以通过 https://console.cloud.google.com
生成新密钥
引用文档
https://firebase.google.com/docs/cloud-messaging/concept-options#credentials
Server key: A server key that authorizes your app server for access to
Google services, including sending messages via Firebase Cloud
Messaging. [...]
Important: Do not include the server key anywhere in your client code.
Also, make sure to use only server keys to authorize your app server.
Android, iOS, and browser keys are rejected by FCM.
今天我想从 GCM 切换到 FCM,所以我设置了所需的一切并希望实现服务器端代码。我使用了 gcm4j 库并将其更改为地址为 https://fcm.googleapis.com/fcm/send
。
所以我正在做以下事情:
FCM fcm = new FCMDefault(new FCMConfig().withKey(FCMGlobals.FCM_API_KEY));
FCMRequest request = new FCMRequest().withRegistrationId(android.getRegistration())
// .withCollapseKey(collapseKey)
.withDelayWhileIdle(true)
.withDataItem(FCMGlobals.FCM_PARAM_CODE, code)
.withDataItem(FCMGlobals.FCM_PARAM_USER_ID, "" + user.getId())
.withDataItem(FCMGlobals.FCM_PARAM_ADDITION, "" + addition);
ListenableFuture<FCMResponse> responseFuture = fcm.send(request);
Futures.addCallback(responseFuture, new FutureCallback<FCMResponse>() {
public void onFailure(Throwable t) {
log.error(t);
}
@Override
public void onSuccess(FCMResponse response) {
log.info(response.toString());
}
});
其实现是:
protected FCMResponse executeRequest(FCMRequest request) throws IOException {
byte[] content = this.objectMapper.writeValueAsBytes(request);
HttpURLConnection conn = this.connectionFactory.open(this.fcmUrl);
conn.setRequestMethod("POST");
conn.addRequestProperty("Authorization", getAuthorization(request));
conn.addRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setFixedLengthStreamingMode(content.length);
LoggerFactory.getLogger("FCMDefaultAbstract").info("Authorization: " + conn.getRequestProperty("Authorization"));
LoggerFactory.getLogger("FCMDefaultAbstract").info("Content-Type: " + conn.getRequestProperty("Content-Type"));
LoggerFactory.getLogger("FCMDefaultAbstract").info("send: " + new String(content));
try (OutputStream outputStream = conn.getOutputStream()) {
IOUtils.write(content, outputStream);
} catch (Exception e) {
throw new FCMNetworkException("Error sending HTTP request to FCM", e);
}
FCMResponse response;
try (InputStream inputStream = conn.getInputStream()) {
response = this.objectMapper.readValue(IOUtils.toByteArray(inputStream), FCMResponse.class);
} catch (IOException e) {
try (InputStream inputStreamError = conn.getErrorStream()) {
String str = inputStreamError != null ? IOUtils.toString(inputStreamError) : "No error details provided";
int responseCode = conn.getResponseCode();
if (responseCode < 500) {
throw new FCMNetworkException(conn.getResponseCode(), str.trim(), e);
} else {
throw new FCMNetworkException(conn.getResponseCode(), str.trim(), checkForRetryInResponse(conn), e);
}
}
}
response.setRequest(request);
response.setRetryAfter(checkForRetryInResponse(conn));
Iterator<String> iteratorId = request.getRegistrationIds().iterator();
Iterator<FCMResult> iteratorResponse = response.getResults().iterator();
while (iteratorId.hasNext() && iteratorResponse.hasNext()) {
iteratorResponse.next().setRequestedRegistrationId(iteratorId.next());
}
if (iteratorId.hasNext()) {
LOG.warn("Protocol error: Less results than requested registation IDs");
}
if (iteratorResponse.hasNext()) {
LOG.warn("Protocol error: More results than requested registation IDs");
}
return response;
}
这里是日志输出:
FCMDefaultAbstract Authorization: null
FCMDefaultAbstract Content-Type:application/json
FCMDefaultAbstract send: {"registration_ids":["dMpvzp*************************************2lRsSl_5lFET2"],"data":{"CODE":"201","USER_ID":"1","ADDITION":"1468083549493"},"delay_while_idle":true}
FCM FCMNetworkException: HTTP 401: No error details provided
Authorization
header 实际上不为空。它已使用我的 FCM API 密钥正确设置。如果有人试图访问 Authorization
密钥,只有 HTTPUrlConnection
实现会说 return null。
如您所见,我无法连接 FCM。代码 401
表示身份验证失败。
这可能是什么问题?
检查您使用的是 server type
API-KEY,而不是 client
或 browser
API-KEY。
如果您使用的是 Firebase,您可以在
中找到 API-KEY
项目设置 > 云消息
如果您正在使用云控制台,或者您不确定您使用的是哪个密钥, 您可以通过 https://console.cloud.google.com
生成新密钥引用文档
https://firebase.google.com/docs/cloud-messaging/concept-options#credentials
Server key: A server key that authorizes your app server for access to Google services, including sending messages via Firebase Cloud Messaging. [...]
Important: Do not include the server key anywhere in your client code. Also, make sure to use only server keys to authorize your app server. Android, iOS, and browser keys are rejected by FCM.