为啥我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function

Posted

技术标签:

【中文标题】为啥我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function【英文标题】:Why does my cloud function return an exception with code INTERNAL and details null with Unhandled error TypeError: is not a function为什么我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function 【发布时间】:2020-11-28 20:07:37 【问题描述】:

我第一次尝试在我的 android 应用中使用 Firebase Cloud Functions。我得到的输出是代码“INTERNAl”和详细信息“null”的异常。

下面是我的云函数文件index.js:

"use strict";

const functions = require('firebase-functions');

// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions

var crypto = require('crypto');

class PaytmChecksum 

    static encrypt(input, key) 
        var cipher = crypto.createCipheriv('AES-128-CBC', key, PaytmChecksum.iv);
        var encrypted = cipher.update(input, 'binary', 'base64');
        encrypted += cipher.final('base64');
        return encrypted;
    
    static decrypt(encrypted, key) 
        var decipher = crypto.createDecipheriv('AES-128-CBC', key, PaytmChecksum.iv);
        var decrypted = decipher.update(encrypted, 'base64', 'binary');
        try 
            decrypted += decipher.final('binary');
        
        catch (e) 
            console.log(e);
            throw new functions.https.HttpsError('decryption-failed', e);
        
        return decrypted;
    
    static generateSignature(params, key) 
        if (typeof params !== "object" && typeof params !== "string") 
            var error = "string or object expected, " + (typeof params) + " given.";
            //throw new functions.https.HttpsError('generate-signature-failed', error);
            return Promise.reject(error);
        
        if (typeof params !== "string")
            params = PaytmChecksum.getStringByParams(params);
        
        return PaytmChecksum.generateSignatureByString(params, key);
    


    static verifySignature(params, key, checksum) 
        if (typeof params !== "object" && typeof params !== "string") 
            var error = "string or object expected, " + (typeof params) + " given.";
            //throw new functions.https.HttpsError('verify-signature-failed', error);
            return Promise.reject(error);
        
        if(params.hasOwnProperty("CHECKSUMHASH"))
            delete params.CHECKSUMHASH
        
        if (typeof params !== "string")
            params = PaytmChecksum.getStringByParams(params);
        
        return PaytmChecksum.verifySignatureByString(params, key, checksum);
    

    static async generateSignatureByString(params, key) 
        var salt = await PaytmChecksum.generateRandomString(4);
        return PaytmChecksum.calculateChecksum(params, key, salt);
    

    static verifySignatureByString(params, key, checksum) 
        var paytm_hash = PaytmChecksum.decrypt(checksum, key);
        var salt = paytm_hash.substr(paytm_hash.length - 4);
        return (paytm_hash === PaytmChecksum.calculateHash(params, salt));
    

    static generateRandomString(length) 
        return new Promise((resolve, reject) => 
            crypto.randomBytes((length * 3.0) / 4.0, (err, buf) => 
                if (!err) 
                    var salt = buf.toString("base64");
                    resolve(salt);
                
                else 
                    console.log("error occurred in generateRandomString: " + err);
                    //throw new functions.https.HttpsError('generate-random-string-error', err);
                    reject(err);
                
            );
        );
    

    static getStringByParams(params) 
        var data = ;
        Object.keys(params).sort().forEach((key,value) => 
            data[key] = (params[key] !== null && params[key].toLowerCase() !== "null") ? params[key] : "";
        );
        return Object.values(data).join('|');
    

    static calculateHash(params, salt) 
        var finalString = params + "|" + salt;
        return crypto.createHash('sha256').update(finalString).digest('hex') + salt;
    
    static calculateChecksum(params, key, salt) 
        var hashString = PaytmChecksum.calculateHash(params, salt);
        return PaytmChecksum.encrypt(hashString,key);
    

PaytmChecksum.iv = '@@@@&&&&####$$$$';

exports.generateSignature = functions.https.onCall((data, context) => 
    // Checking that the user is authenticated.
    if (!context.auth) 
        // Throwing an HttpsError so that the client gets the error details.
        throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
            'while authenticated.');
    
    let paymentChecksum = new PaytmChecksum();
    let result = paymentChecksum.generateSignature(data.params, data.key);
    return result;
);

这是我调用函数并处理它的响应的活动:

    private void getChecksum(String orderId, String mId) 

        Map<String, String> params = new HashMap<>();
        params.put("MID", mId);
        params.put("ORDERID", orderId);

        String key = "000000000000000000";

        Task<String> taskData = generateSignature(params, key);
        taskData.addOnSuccessListener(this, new OnSuccessListener<String>() 
            @Override
            public void onSuccess(String s) 
                Log.d(TAG, "onSuccess: paytmChecksum" + s);
            
        ).addOnFailureListener(this, new OnFailureListener() 
            @Override
            public void onFailure(@NonNull Exception e) 
                FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
                FirebaseFunctionsException.Code code = ffe.getCode();
                Object details = ffe.getDetails();
                Toast.makeText(getApplicationContext(), code + " " + details, Toast.LENGTH_LONG).show();
            
        );
    

    private Task<String> generateSignature(Map<String, String> params, String merchantKey) 

        Map<String, Object> data = new HashMap<>();
        data.put("params", params);
        data.put("key", merchantKey);

        return mFunctions.getHttpsCallable("generateSignature").call(data).continueWith(
                task -> (String) task.getResult().getData()
        );
    

当我运行此代码时,我看到一个显示“INTERNAL null”的 toast。此外,在 Cloud Functions 控制台日志中,这是错误:

generateSignature
Unhandled error TypeError: paymentChecksum.generateSignature is not a function
at exports.generateSignature.functions.https.onCall (/srv/index.js:112:34)
at func (/srv/node_modules/firebase-functions/lib/providers/https.js:272:32)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)

为什么会出现此错误?有人可以帮忙吗?我无法理解为什么它说它不是一个函数。我在网上查了很多样品。请指导我如何编写正确的可调用云函数。提前致谢! :)

【问题讨论】:

【参考方案1】:

您在函数日志中收到错误消息,因为您尝试将静态函数 generateSignature 作为对象上的方法调用,这是无效的。

您的代码组织有些奇怪。 PaytmChecksum 只包含静态方法,这意味着像现在这样尝试创建它的实例没有真正的价值。如果你只想在某个类上调用静态方法,完全跳过new,直接调用PaytmChecksum.generateSignature()

【讨论】:

以上是关于为啥我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的函数不返回新字符串?

有时我的云函数会从 Firestore 返回旧数据。是缓存问题吗?

为啥我会收到带有 std::bind() 的“本地临时返回地址”警告?

为啥返回带有箭头函数的对象时,array.map 中需要 return 关键字?

为啥 WPF 将我的数据上下文设置为 MS.Internal.NamedObject?

警告:将列添加到从函数返回的 data.table 时“检测到无效 .internal.selfref”