我正在尝试为我的一个用户创建一个FCM设备组,但在发布create
请求时,我得到401 reponse code
:
以下是我的POST
请求:
if let url = URL(string: "https://android.googleapis.com/gcm/notification") {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue(apiKey, forHTTPHeaderField: "Authorization")
request.addValue(senderId, forHTTPHeaderField: "project_id")
let registration_ids = [deviceToken] as! [String]
let jsonToSend = ["operation": "create",
"notification_key_name": LocalUser.shared.firebaseId,
"registration_ids": registration_ids
] as [String : Any]
do {
let jsonData = try JSONSerialization.data(withJSONObject: jsonToSend, options: JSONSerialization.WritingOptions.prettyPrinted)
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response.debugDescription)")
} else if let httpStatus = response as? HTTPURLResponse {
print("statusCode is \(httpStatus.statusCode)")
print("response = \(response.debugDescription)")
}
}
task.resume()
} catch {
print("could not serialize json")
}
}
如果我尝试使用已存在的device group
创建notification_key_name
,您也知道会发生什么。是否会将新device key
添加到现有组中?或者有没有办法检查一个组是否存在?
答案 0 :(得分:2)
在此声明中:
request.addValue(apiKey, forHTTPHeaderField: "Authorization")
apiKey
必须是项目设置中的服务器密钥,前缀为key=
。
例如:key=AAAPWK_CVGw:APA91b...saklHTO29fTk
您在评论中表明您是从客户端设备执行此操作。将服务器密钥放入设备代码中并不安全。
更安全的替代方法是在云功能中执行设备组创建。以下是通过将组创建参数存储在数据库中而触发的基本实现。仅举例;未彻底测试;更正/评论欢迎。
const rqstProm = require('request-promise');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.createDeviceGroup = functions.database.ref("/deviceGroup/create/params")
.onWrite(event => {
const serverKey = 'AAAAXp6june:APA91bF-Nq9pm...3dD5pZxVsNBfX0O3_Xf-jV472nfn-sb';
const senderId = '271828182845';
// TODO add checks for valid request params
const request = event.data.val();
const groupName = request.groupName;
const tokens = Object.keys(request.tokens);
console.log('groupName=', groupName, 'tokens=', tokens.length);
const options = {
method: 'POST',
uri: 'https://android.googleapis.com/gcm/notification',
headers: {
'Authorization': 'key=' + serverKey,
'project_id': senderId
},
body: {
operation: 'create',
notification_key_name: groupName,
registration_ids: tokens
},
json: true
};
const resultRef = admin.database().ref('deviceGroup/create/result/key');
return rqstProm(options)
.then((parsedBody) => {
console.log('SUCCESS response=', parsedBody);
return resultRef.set(parsedBody.notification_key);
})
.catch((err) => {
console.log('FAILED err=', err);
return resultRef.set('ERROR: ' + err);
});
});
使用云功能创建设备组的示例代码(Android):
private ValueEventListener resultListener;
private void createDeviceGroup(String groupName, String ...deviceTokens) {
final DatabaseReference baseRef =
FirebaseDatabase.getInstance().getReference("deviceGroup/create");
final DatabaseReference resultRef = baseRef.child("result");
// listener to get the result of the group creation request
resultListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snap) {
if (snap.exists()) {
// got the result; stop listening
resultRef.removeEventListener(resultListener);
String key = snap.child("key").getValue(String.class);
Log.d(TAG, "createDeviceGroup: key=" + key);
} else {
// we get here when listener is first attached
Log.w(TAG, "createDeviceGroup: No Result");
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
resultRef.removeEventListener(resultListener);
throw databaseError.toException();
}
};
// remove any previous result
resultRef.removeValue();
// start listening for a result
resultRef.addValueEventListener(resultListener);
// build the request params
final Map<String,Object> request = new HashMap<>();
final Map<String,Object> tokens = new HashMap<>();
// creation of device group requires a name and set of tokens
request.put("groupName", groupName);
request.put("tokens", tokens);
for (String token : deviceTokens) {
// tokens are stored as keys; value is not significant
tokens.put(token, true);
}
// write the request; this triggers Cloud Function to create device group
baseRef.child("params").setValue(request);
}
这是成功创建组后的数据库布局:
{
"deviceGroup": {
"create": {
"params": {
"groupName": "testGroupA",
"tokens": {
"ccVDiSO1tbc:APA91bE3pELSz...oDqY_ioLRj4xUnk5mci6ateFRVe" : true,
"pqUYfyTbuax:APA91bE3pELSz...oDqY_ioLRj4xUnk5mci6ateFRVe" : true,
"tyKUY1mrUR8:APA91bE3pELSz...oDqY_ioLRj4xUnk5mci6ateFRVe" : true
}
},
"result": {
"key": "APA91bEY678qaLUAB1tOPv...tZ9IG64H7b0KtOo-hSJdsoovmuRe2eCyoUeu4qs"
}
}
}
}