You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用原生JSON调用Firebase云函数?iOS调用checkUsers遇422错误

问题分析

你遇到的问题根源在于Firebase HTTPS Callable函数和普通HTTP POST请求的参数传递格式完全不同。你的云函数是按照普通Express POST请求的逻辑读取req.body.emails,但iOS端用了httpsCallable方法调用——这种方式会把参数包裹在特定的data结构里,导致云函数找不到req.body.emails,从而触发422错误提示。

下面给你两种针对性的解决方案,你可以根据自己的需求选择:

方案1:修改iOS代码,使用普通HTTP POST请求

既然你的云函数已经适配了Postman的普通POST请求,那iOS端可以直接发送标准POST请求,不用Callable函数:

func checkEmails( _ contacts: [SIContact], _ completion: @escaping (([SIContact]) -> Void) ) {
    // 替换成你的云函数实际URL
    guard let url = URL(string: "https://your-cloud-function-domain.cloudfunctions.net/checkUsers") else {
        print("Invalid cloud function URL")
        return completion(contacts)
    }
    
    let data = ["aaa", "akshit.zaveri@gmail.com", "bbb"]
    let params = ["emails": data]
    
    do {
        let jsonData = try JSONSerialization.data(withJSONObject: params)
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = jsonData
        
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            if let error = error {
                print("Error while checking emails \(error)")
                return completion(contacts)
            }
            
            guard let responseData = data else {
                print("No response data received")
                return completion(contacts)
            }
            
            do {
                guard let results = try JSONSerialization.jsonObject(with: responseData) as? [[String: Any]] else {
                    print("Invalid response format from cloud function")
                    return completion(contacts)
                }
                print(results)
                // 这里可以根据results更新contacts后再调用completion
                completion(contacts)
            } catch {
                print("Failed to parse response: \(error)")
                completion(contacts)
            }
        }.resume()
    } catch {
        print("Failed to serialize request params: \(error)")
        completion(contacts)
    }
}

方案2:修改云函数,适配HTTPS Callable格式

如果你想继续用iOS的httpsCallable方法,需要调整云函数的参数读取逻辑——Callable函数的参数会放在req.body.data里,而非直接在req.body,同时建议用异步写法简化代码:

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

exports.checkUsers = functions.https.onCall(async (data, context) => {
    // 从Callable函数的data对象中获取emails
    if (data.emails === undefined) {
        throw new functions.https.HttpsError('invalid-argument', 'Missing email addresses input');
    }
    
    const emailsToCheck = data.emails;
    if (emailsToCheck.length === 0) {
        throw new functions.https.HttpsError('invalid-argument', 'No email addresses provided');
    }
    
    const existingEmails = [];
    
    // 异步遍历所有用户(避免回调嵌套)
    let pageToken;
    do {
        const userPage = await admin.auth().listUsers(1000, pageToken);
        userPage.users.forEach(user => {
            existingEmails.push(user.email.toLowerCase());
        });
        pageToken = userPage.pageToken;
    } while (pageToken);
    
    // 检查每个邮箱是否存在
    const emailsChecked = emailsToCheck.map(email => ({
        email: email,
        exists: existingEmails.includes(email.toLowerCase())
    }));
    
    return emailsChecked;
});

注意:改用Callable函数后,Postman的调用方式也要调整——POST请求的Body需要是{"data": {"emails": ["aaa", "akshit.zaveri@gmail.com", "bbb"]}},同时请求头要包含Content-Type: application/json。

内容的提问来源于stack exchange,提问作者Akshit Zaveri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:57:35