云功能Firebase无法正常运行

时间:2019-10-18 20:28:02

标签: firebase google-cloud-firestore google-cloud-functions

我创建了一个函数来检查google play的应用内付款,并在一切正常的情况下执行一些操作。

这是我的功能:

exports.validatePurchases = functions.firestore
    .document('users/{userID}/purchasesRemoveAds/{documentID}')
    .onCreate(async (snap, context) => {

        const userID = context.params.userID;

        const purchase = snap.data();
        if (!purchase) {
            return null
        } else {
            if (purchase.is_processed === true) {
                console.log('Purchase already processed!, exiting');
                return null;
            }
            // const orderId = context.params.orderId;
            // const dbRoot = event.ref.root;
            const packageName = purchase.packageName;
            const productId = purchase.productId;
            const purchaseToken = purchase.purchaseToken;

            authClient.authorize()
            // authClient.authorize() returns a credentials Object
                .then(credentials => {
                    console.log(credentials, productId, purchaseToken);
                    return playDeveloperApiClient.purchases.products.get({
                        auth: authClient,
                        packageName: packageName,
                        productId: productId,
                        token: purchaseToken
                    });
                })
                // publisher.purchases.products.get() Returns a axiosResponse object with Purchase data within and the status that should be enough for the validation
                .then((axiosResponse) => {
                    console.log(`Status Code: ${axiosResponse.status} Purchase state: ${ axiosResponse.data.purchaseState} ${typeof axiosResponse.status} ${typeof axiosResponse.data.purchaseState}`);
                    if (axiosResponse.status === 200 && axiosResponse.data.purchaseState === 0) {
                        console.log('ok here');
                        // Your purchase is valid, do your thing
                        return changeShowAdsFalse(userID);
                    } else {
                        console.log(typeof axiosResponse.status);
                    }
                    return null;
                })
                .catch(reason => {
                    console.log(`Rejection Code: ${reason.code}`);
                    console.log(`Rejection Message: ${reason.message}`);
                    return null;
                });


            return null;
        }
    });

这很简单,它监听firestore数据库,当目录中有一个新文档时,它将触发该功能。 然后从文档中获取数据,并使用playDeveloperApiClient.purchases.products.get获取购买,然后使用axiosResponse检查新数据并获取购买状态。 在那之后,它应该检查状态== 200和purchaseState == 0,这是发生的事情(我看到了,因为我记录了这些值),但此后没有发生任何事情。 如果不执行,则不执行。 另一个奇怪的事情是,在第一条日志和第二条日志通过之前,将近一分钟或更长时间。

我在firebase上有一个大火计划,并且没有任何信用卡关联。

我不知道发生了什么


云功能的日志为:

10:14:22.856 PM
validatePurchases
Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions

10:14:23.561 PM
validatePurchases
Function execution took 706 ms, finished with status: 'ok'

10:14:24.457 PM
validatePurchases
{ access_token: 'token.AO-token-token',
  token_type: 'Bearer',
  expiry_date: 1571433263000,
  id_token: undefined,
  refresh_token: 'jwt-placeholder' } 'remove_ads' 'token.AO-token-token'

10:14:27.457 PM
validatePurchases
Status Code: 200 Purchase state: 0 number number

1 个答案:

答案 0 :(得分:2)

您的Cloud Function中需要调整几个要点。

首先,您需要配置您的计费帐户,如错误日志中所述。显然,您所呼叫的服务不被视为Google拥有的服务,因此您需要制定“有效”的Flame或Blaze计划。请参见https://firebase.google.com/pricing/(将鼠标悬停在“云函数”标题之后的问号上)


第二,您通过执行来链接不同的承诺

        authClient.authorize()
            .then(credentials => {
                //....
                return playDeveloperApiClient.purchases.products.get();
            })
            .then((axiosResponse) => {..})
            .catch(reason => {
                //....
                return null;
            });

但是您不会返回链中的第一个Promise:您应该执行return authClient.authorize()


第三,在承诺链的平行部分(或中间),您执行return null;

        authClient.authorize()
            .then(credentials => {...})
            .then((axiosResponse) => {..})
            .catch(reason => {...});

        return null;   //  <--- !!

            .then((axiosResponse) => {
                if (axiosResponse.status === 200 && axiosResponse.data.purchaseState === 0) {
                    return changeShowAdsFalse(userID);
                } else {
                    console.log(typeof axiosResponse.status);
                    //Here you should do something, i.e. throw an error
                }
                return null;   //  <--- !!
            });

第四,由于您使用then()方法来链接诺言,因此可以在async方法中删除onCreate()关键字。


因此,在配置您的计费帐户之后,以下方法可以解决问题。但是请注意,我没有看到changeShowAdsFalse()函数的代码,但是我根据您上面的评论做出了一个假设,即它返回了Promise。

exports.validatePurchases = functions.firestore
    .document('users/{userID}/purchasesRemoveAds/{documentID}')
    .onCreate((snap, context) => {

        const userID = context.params.userID;
        const purchase = snap.data();

        if (!purchase) {
            return null;
        } else {
            if (purchase.is_processed === true) {
                console.log('Purchase already processed!, exiting');
                return null;
            }

            const packageName = purchase.packageName;
            const productId = purchase.productId;
            const purchaseToken = purchase.purchaseToken;

            return authClient.authorize()
                .then(credentials => {
                    return playDeveloperApiClient.purchases.products.get({
                        auth: authClient,
                        packageName: packageName,
                        productId: productId,
                        token: purchaseToken
                    });
                })
                .then((axiosResponse) => {
                    if (axiosResponse.status === 200 && axiosResponse.data.purchaseState === 0) {
                        return changeShowAdsFalse(userID);
                    } else {
                        console.log(typeof axiosResponse.status);
                        throw new Error("Wrong type: " + typeof axiosResponse.status);
                    }
                })
                .catch(reason => {
                    console.log(`Rejection Code: ${reason.code}`);
                    console.log(`Rejection Message: ${reason.message}`);
                    return null;
                });

        }

    });