【问题标题】:Firebase function call return value in SwiftSwift中的Firebase函数调用返回值
【发布时间】:2020-01-20 21:36:58
【问题描述】:

我正在尝试使用 Swift 访问从 Firebase 函数 twilioToken 返回的令牌,就像使用 Redux JS 一样。我附上了我用于 JS 的代码,所以我可以用 Swift 模仿它,但不确定如何从 firebase 函数调用中访问 result.token。我在这里错过了什么吗?我是否需要以不同的方式从 https 请求中获取值,或者我是否使用当前代码关闭?如果我需要详细说明,请告诉我,谢谢!

output.token 上的当前错误是 Value of tuple type 'Void' has no member 'token'

尝试的 Swift 代码:

import UIKit
import MBProgressHUD
import FirebaseFunctions

class CallRoomVC: UIViewController {
    private var appDelegate: AppDelegate!
    private var userSession: UserSession = FirebaseUserSession.shared

    lazy var functions = Functions.functions()

    override func viewDidLoad() {
        super.viewDidLoad()
        appDelegate = UIApplication.shared.delegate as? AppDelegate

    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        guard let user = userSession.user else {
            fatalError("User instance must be created")
        }

        var output = functions.httpsCallable("twilioToken").call(["uid": user.id]) { (result, error) in
            if let error = error as NSError? {
                if error.domain == FunctionsErrorDomain {
                    let code = FunctionsErrorCode(rawValue: error.code)
                    let message = error.localizedDescription
                    let details = error.userInfo[FunctionsErrorDetailsKey]
                }
                // ...
                // or
                // print("Result: \(result.token)")
            }

        }
        if (output != nil) {
            print("Result: \(output.token)")
        }
    }
}

Firebase 功能:

"use strict";
const functions = require("firebase-functions");
const admin = require("firebase-admin");
// eslint-disable-next-line import/no-extraneous-dependencies
const google_cloud_logging = require("@google-cloud/logging");
const twilio = require("twilio");
const cors = require("cors")({
  origin: true
});
// eslint-disable-next-line import/no-extraneous-dependencies
admin.initializeApp(functions.config().firebase);

exports.twilioToken = functions.https.onRequest((req, res) => {
  return cors(req, res, () => {
    const token = new twilio.jwt.AccessToken(
      "xxxxxxxxxxxxxx", // Account ID
      "xxxxxxxxxxxxxx", // API Key SID
      "xxxxxxxxxxxxxx" // API Key Secret
    );
    token.identity = req.query.uid;
    token.addGrant(new twilio.jwt.AccessToken.VideoGrant());
    console.log("Sending token: ", token);
    res.status(200).send({ token: token.toJwt() });
  });
});

JS Redux 代码:

function* getTokenSaga(action) {
  const token = yield call(
    rsf.functions.call,
    "twilioToken",
    {
      uid: action.uid
    },
    {
      method: "GET"
    }
  );

  yield put(retrievedToken(token.token));
}

export function* twilioRootSaga() {
  yield all([takeEvery(types.TOKEN.GET, getTokenSaga)]);
}

【问题讨论】:

  • 开始,存储output是没用的;您的请求结果完全在call 的关闭中处理。你在result 对象中究竟得到了什么?
  • @MichaelFourre 抱歉正在测试,我只能让它返回nil
  • @MichaelFourre 返回的令牌值是否应该出现在该结果中?因为问题可能出在其他地方
  • 根据我所看到的,它应该。为了继续前进,您可能希望验证从请求到结果的每一步,以确保您的问题不会介于两者之间。如果您更新了您的问题以显示您的问题出现的确切时间,那么诊断和提供解决方案会容易得多。
  • 好的,谢谢,我会反馈的。

标签: swift google-cloud-functions twilio


【解决方案1】:

Phil Nash 对 Swift 方面的解释奏效了,但问题在于我的 Firebase 函数,我必须根据 Twilio/Firebase Function API 文档为其创建一个新函数:

exports.twilioTokenV2 = functions.https.onCall((data, context) => {
    const AccessToken = twilio.jwt.AccessToken;
    const VideoGrant = AccessToken.VideoGrant;
    const twilioAccountSid = functions.config().twilio_api.account_sid;
    const twilioApiKey = functions.config().twilio_api.key;
    const twilioApiSecret = functions.config().twilio_api.secret;
    // Grab uid passed in for identity
    const identity = data.uid;

    // Grab question ID passed in for room name
    const videoGrant = new VideoGrant({
      room: data.qid,
    });

    // Create an access token which we will sign and return to the client,
    // containing the grant we just created
    const token = new AccessToken(twilioAccountSid, twilioApiKey, twilioApiSecret);
    token.addGrant(videoGrant);
    token.identity = identity;

    console.log("Sending token: ", token);
    return {
      token: token.toJwt()
    }

});

【讨论】:

    【解决方案2】:

    这里是 Twilio 开发者宣传员。

    您对 Firebase 函数的调用是异步的,因为它发出的是 HTTP 请求。结果不会返回到您的output 变量,但它在回调中作为result 对象可用。您需要改用 result,如下所示:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    
        guard let user = userSession.user else {
            fatalError("User instance must be created")
        }
    
        functions.httpsCallable("twilioToken").call(["uid": user.id]) { (result, error) in
            if let error = error as NSError? {
                if error.domain == FunctionsErrorDomain {
                    let code = FunctionsErrorCode(rawValue: error.code)
                    let message = error.localizedDescription
                    let details = error.userInfo[FunctionsErrorDetailsKey]
                }
            }
            if let token = (result?.data as? [String: Any])?["token"] as? String {
                print("Result: \(token)")
            }
        }
    
    }
    

    这个例子改编自the Firebase documentation here

    如果有帮助,请告诉我。

    【讨论】:

    • 我认为这应该可以解决问题,很确定在管道的更深处出现了问题。我正在尝试使用 Twilio 函数的替代解决方案,但在本教程 (youtube.com/watch?v=5lrdYBLEk60) 之后仍然遇到问题,并返回“无效访问令牌”代码 20101。如果您对此有任何想法,我在这里提出了另一个问题:stackoverflow.com/questions/58107499/…
    猜你喜欢
    • 2017-10-18
    • 2017-08-11
    • 2021-12-06
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    相关资源
    最近更新 更多