当前位置: 首页 > 知识库问答 >
问题:

Firebase Cloud Functions代币

程墨竹
2023-03-14

我需要帮助。node.js编写的云功能正在抛出错误,并且不会在我的Android java应用程序中引起推送通知(警报)提醒已发表评论或用户喜欢帖子。在Firebase Console上,我能够在云功能日志中获取错误消息:

Successfully sent message: { results: [ { error: [Object] } ],
canonicalRegistrationTokenCount: 0,
failureCount: 1,
successCount: 0,
multicastId: 7952971403531609000 }

当我在Firebase Cloud函数日志上查看错误消息时,我还得到以下信息:

Error: { Error: The provided registration token is not registered. A previously valid registration token can be unregistered for a variety of reasons. See the error documentation for more details. Remove this registration token and stop using it to send messages.
at FirebaseMessagingError.Error (native)
at FirebaseMessagingError.FirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseMessagingError.PrefixedFirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseMessagingError (/user_code/node_modules/firebase-admin/lib/utils/error.js:253:16)
at Function.FirebaseMessagingError.fromServerError (/user_code/node_modules/firebase-admin/lib/utils/error.js:283:16)
at /user_code/node_modules/firebase-admin/lib/messaging/messaging.js:381:63
at Array.forEach (native)
at mapRawResponseToDevicesResponse (/user_code/node_modules/firebase-admin/lib/messaging/messaging.js:377:26)
at /user_code/node_modules/firebase-admin/lib/messaging/messaging.js:558:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
errorInfo:
{ code: 'messaging/registration-token-not-registered',
message: 'The provided registration token is not registered. A previously valid registration token can be unregistered for a variety of reasons. See the error documentation for more details. Remove this registration token and stop using it to send messages.' },
codePrefix: 'messaging' }

信息非常明确:以前有效的注册令牌可能因各种原因而被取消注册。我看过关于这些错误主题的其他帖子,但没有一篇文章确切概述了如何在注册和登录期间处理和使用令牌。

以下是Firebase云函数代码。。。

'use-strict'

const functions = require('firebase-functions');
const admin=require('firebase-admin');
admin.initializeApp(functions.config().firebase);


exports.sendCommentNotification=functions.firestore.document("Notifications/{user_id}/Comment/{comment_id}").onWrite((change,context)=> {

    const user_id=context.params.user_id;
    const comment_id=context.params.comment_id;

  console.log(user_id+":"+comment_id);

  return admin.firestore().collection("Notifications").doc(user_id).collection("Comment").doc(comment_id).get().then((queryResult)=>{

        const post_id=queryResult.data().post_id;
        const admin_user_id=queryResult.data().admin_id;
        const noti_id=queryResult.data().notification_id;
        const timestamp=queryResult.data().timestamp;    
        const post_desc=queryResult.data().post_desc;

        const admin_data=admin.firestore().collection("Users").doc(admin_user_id).get();
        const commenter_data=admin.firestore().collection("Users").doc(user_id).get();

        return Promise.all([commenter_data,admin_data]).then(result=>{

            const commenter_name=result[0].data().name;
            const commenter_image=result[0].data().image;
            const admin_token=result[1].data().token_id;
            const admin_name=result[1].data().name;

           if(commenter_name!=admin_name)
           {
               const payload={
               data:{
                notification_id:noti_id,
                timestamp:timestamp,
                post_id:post_id,
                admin_id:admin_user_id,
                title:commenter_name,
                from_image:commenter_image,

                post_desc:post_desc,
                body:"Commented on your post",
                click_action:"com.app.ej.ms.TARGET_COMMENT"
              }

            };


           admin.messaging().sendToDevice(admin_token,payload).then(function (response) {
            console.log("Successfully sent message:", response);
            return;
            })
            .catch(function (error) {
                console.log("Error sending message:", error);
            });


           }

          });
    });

});

...

这里是注册活动。JAVA

...

private void registerUser() {

        mAuth.createUserWithEmailAndPassword(email_, pass_).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull final Task<AuthResult> task) {
                if (task.isSuccessful()) {

                    Map<String,Object> usernameMap=new HashMap<String, Object>();
                    usernameMap.put("username",username_);

                    firebaseFirestore.collection("Usernames")
                            .document(username_)
                            .set(usernameMap)
                            .addOnSuccessListener(new OnSuccessListener<Void>() {
                                @Override
                                public void onSuccess(Void aVoid) {
                                    task.getResult()
                                            .getUser()
                                            .sendEmailVerification()
                                            .addOnSuccessListener(new OnSuccessListener<Void>() {
                                                @Override
                                                public void onSuccess(Void aVoid) {

                                                    final String userUid = task.getResult().getUser().getUid();
                                                    final StorageReference user_profile = storageReference.child(userUid + ".png");
                                                    user_profile.putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                                                        @Override
                                                        public void onComplete(@NonNull final Task<UploadTask.TaskSnapshot> task) {
                                                            if (task.isSuccessful()) {

                                                               user_profile.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                                                                   @Override
                                                                   public void onSuccess(Uri uri) {

                                                                       //String token_id = FirebaseInstanceId.getInstance().getToken(); // Deprecated
                                                                       // TODO https://firebase.google.com/docs/cloud-messaging/android/client#retrieve-the-current-registration-token.
                                                                       // FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( RegisterActivity.this,  new OnSuccessListener<InstanceIdResult>() {

                                                                       FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
                                                                           @Override
                                                                           public void onComplete(@NonNull Task<InstanceIdResult> task) {
                                                                               if (!task.isSuccessful()) {
                                                                                   Log.w(TAG, "getInstanceId failed", task.getException());
                                                                                   return;
                                                                               }
                                                                               // String token_id = instanceIdResult.getToken();
                                                                               String token_id = task.getResult().getToken();
                                                                               Log.i(TAG, "RegisterActivity Token ID (token_id): " + token_id);

                                                                               Map<String, Object> userMap = new HashMap<>();
                                                                               userMap.put("id", userUid);
userMap.put("name", name_);
userMap.put("image", uri.toString());
userMap.put("email", email_);
userMap.put("bio",getString(R.string.default_bio));
userMap.put("username", username_);
userMap.put("location", location_);
userMap.put("token_id", ""); //token_id

                           firebaseFirestore.collection("Users").document(userUid).set(userMap).addOnSuccessListener(new OnSuccessListener<Void>() {
                                                                                   @Override
                                                                                   public void onSuccess(Void aVoid) {
                                                                                       mDialog.dismiss();
                                                                                       Toast.makeText(RegisterActivity.this, "Verification email sent", Toast.LENGTH_SHORT).show();
                                                                                       finish();
                                                                                   } 

...

这是在LoginActivity.java

...

public void performLogin(final boolean override) {

        final String email_, pass_;
        email_ = email.getText().toString();
        pass_ = password.getText().toString();

        if (!TextUtils.isEmpty(email_) && !TextUtils.isEmpty(pass_)) {
            mDialog.show();

            mAuth.signInWithEmailAndPassword(email_, pass_).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull final Task<AuthResult> task) {
                    if (task.isSuccessful()) {

                        //Toast.makeText(LoginActivity.this, "Login Successful, continue to email verified", Toast.LENGTH_LONG).show();
                        Log.i(TAG, "Login Successful, continue to email verified");

                        if (task.getResult().getUser().isEmailVerified()) {

                            //Toast.makeText(LoginActivity.this, "Email is verified Successful, continue to get token", Toast.LENGTH_LONG).show();
                            Log.i(TAG, "Email is verified Successful, continue to get token");

                            //final String token_id = FirebaseInstanceId.getInstance().getToken(); Deprecated
                            // FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( LoginActivity.this,  new OnSuccessListener<InstanceIdResult>() {
                            FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
                                @Override
                                public void onComplete(@NonNull Task<InstanceIdResult> task2) {
                                    if (!task2.isSuccessful()) {
                                        Log.w(TAG, "getInstanceId failed", task2.getException());
                                        return;
                                    }

                                    // Get new Instance ID token
                                    String token_id = task2.getResult().getToken();


                                    Log.i(TAG, "Get Token Listener, Token ID (token_id): " + token_id);

                                    final String current_id = task.getResult().getUser().getUid();

                                    mFirestore.collection("Users").document(current_id).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                                        @Override
                                        public void onSuccess(DocumentSnapshot documentSnapshot) {
                                            if (!override) {
                                                if (documentSnapshot.getString("token_id").equals(token_id) || documentSnapshot.getString("token_id").equals("")) {

                                                    Map<String, Object> tokenMap = new HashMap<>();
                                                    tokenMap.put("token_id", token_id);

                                                    mFirestore.collection("Users").document(current_id).update(tokenMap).addOnSuccessListener(new OnSuccessListener<Void>() {
                                                        @Override
                                                        public void onSuccess(Void aVoid) {

                                                            FirebaseFirestore.getInstance().collection("Users").document(current_id).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                                                                @Override
                                                                public void onSuccess(DocumentSnapshot documentSnapshot) {

                                                                    String username = documentSnapshot.getString("username");
                                                                    String name = documentSnapshot.getString("name");
                                                                    String email = documentSnapshot.getString("email");
                                                                    String image = documentSnapshot.getString("image");
                                                                    String password = pass_;
                                                                    String location = documentSnapshot.getString("location");
                                                                    String bio = documentSnapshot.getString("bio");

                                                                    // TODO Added Qiscus login here
                                                                    userHelper.insertContact(username, name, email, image, password, location, bio);
                                                                    loginPresenter.login(name, email, password);

                                                                    // TODO Add to Override option
                                                                    // Original placement of functions:
                                                                    mDialog.dismiss();
                                                                    MainActivity.startActivity(LoginActivity.this);
                                                                    finish();

                                                            }

...

这是我的FCM代码...

public class FCMService extends FirebaseMessagingService {

    private static final String TAG = FCMService.class.getSimpleName();

    private NotificationUtil notificationUtils;
    private String cDesc;


    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        Log.d("NEW_TOKEN",token);

        //String refreshedToken = FirebaseInstanceId.getInstance().getToken(); 
        // Deprecated
        storeRegIdInPref(token);
        sendRegistrationToServer(token);

        Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);
        registrationComplete.putExtra("token", token);
        LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
    }


    private void sendRegistrationToServer(final String token) {
        Log.i(TAG, "sendRegistrationToServer:" + token);
    }

    private void storeRegIdInPref(String token) {
        SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString("regId", token);
        editor.apply();
    }




    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        handleDataMessage(remoteMessage);
    }

   }

...

(编辑)Firestore数据库结构

我很感激弗兰克的回答,但这是我数据库的结构。我理解,我可能需要重新构造数据库,以便它可以同时保存多个token_ID,以便friends/commenter cloud函数可以删除产生错误的token。但坦率地说,我不知道该怎么做。欢迎任何帮助或网站。

共有1个答案

李飞翼
2023-03-14

您的问题中代码太多,所以我没有全部阅读。但错误消息的要点是您正在向FCM发送一个不(或不再知道)的实例ID令牌。您需要从所谓的令牌注册表中删除令牌,通常只是保存令牌的数据库。

关于如何删除过期令牌,我最喜欢的例子是函数-样本repo:

  tokens = Object.keys(tokensSnapshot.val());
  // Send notifications to all tokens.
  const response = await admin.messaging().sendToDevice(tokens, payload);
  // For each message check if there was an error.
  const tokensToRemove = [];
  response.results.forEach((result, index) => {
    const error = result.error;
    if (error) {
      console.error('Failure sending notification to', tokens[index], error);
      // Cleanup the tokens who are not registered anymore.
      if (error.code === 'messaging/invalid-registration-token' ||
          error.code === 'messaging/registration-token-not-registered') {
        tokensToRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
      }
    }
  });
  return Promise.all(tokensToRemove);

上述代码调用sendToDevice(…) ,然后分析过期令牌错误的结果。然后,它会从数据库中删除这些令牌,这样它们就不会一直导致错误。

 类似资料:
  • 问题 你构建了一个自定义容器对象,里面包含有列表、元组或其他可迭代对象。 你想直接在你的这个新容器对象上执行迭代操作。 解决方案 实际上你只需要定义一个 __iter__() 方法,将迭代操作代理到容器内部的对象上去。比如: class Node: def __init__(self, value): self._value = value self._ch

  • 问题内容: 我在做找零钱的问题。我已经解决了这个问题,因为它会打印出我需要进行最少更改的硬币数量,但是我该如何更改程序以使其也打印那些硬币呢? 这是一个示例: 输入: 输出: 目前,我的代码仅返回。 顺便说一句,这只能通过递归来完成。 不允许循环 码: 问题答案: 程序的其他版本: 输出: PS:如果您愿意,我会添加一个说明。

  • 代币信息API,接口的参数说明请参考Etherscan API 约定, 文档中不单独说明。 通过合约地址获取ERC20 Token总供应量 了解ERC20 代币定义与创建 https://api.etherscan.io/api?module=stats&action=tokensupply&contractaddress=0x57d90b64a1a57749b0f932f1a3395792e12

  • 问题内容: 这是一个从来没有一个正确答案的问题,我已经在网上搜索了很多次,却找不到解决方案。 它适用于Firefox,Chrome。我的responseText将像Réunion这样返回char,它将显示为奇怪的符号。 我尝试了许多方法,例如编码和解码,在响应文件中设置标头都无效。我没主意了。请帮助某人。 在主文件中,确保设置了内容类型和字符集。 在您的AJAX加载页面中,确保您位于顶部。 问题解

  • 用于行内代码片断以及更长的、多行代码的样式。 内联代码 用code包裹内联代码片断。勿忘转义HTML尖括号。 For example, <code><section></code> should be wrapped as inline. 预格式化文本 或者说,代码块,使用<pre>的多行代码文本。再一次提醒,请勿忘转义代码中的所有尖括号,以实现正确的渲染。你可以视情况添加.pre-scrolla

  • 你竟任着刚硬不悔改的心,为自己积蓄忿怒,以致神震怒,显他公义审判的日子来到。他必照各人的行为报应各人。凡恒心行善,寻求荣耀、尊贵和不能朽坏之福的,就以永生报应他们;惟有结党不顺从真理,反顺从不义的,就以忿怒、恼恨报应他们。(ROMANS 2:7-8) 迭代 Bill正在介绍他的项目,嘴里不断蹦出“loop、iterate、traversal、recursion”这些单词,夹杂在汉语汇总。旁边的小白