Firebase Cloud Function 无法返回支付订单数据到 Android 端的问题
问题成因与代码修正方案
核心问题点
- 云函数端的两个核心错误:
onCall的回调参数写错了:这个方法的固定入参是「客户端传上来的参数、请求上下文对象」,根本不存在名叫response的参数,原代码把上下文对象错当成响应对象,从根上就不符合云函数的运行规范。- 异步流程没打通:Ippopay 的
createOrder是异步回调接口,原代码在它的回调里写的return,只会返回到 Ippopay 的库代码内部,根本不会作为云函数的返回值发给客户端。云函数发起createOrder请求后,不等回调执行完就直接结束运行了,哪怕日志里能打印出订单数据,也没有通路把数据回传给 Android 端。另外代码完全没处理err报错分支,接口出问题时云函数会直接超时,返回空内容。
- Android 端的两个核心错误:
- 异步时序完全搞反了:Firebase Callable 的网络请求是后台异步跑的,原代码发起
call()请求后,立刻就拿初始值为null的data去更新 TextView,这时候网络请求还没返回,拿到的当然是空值。 - 结果处理位置错了:用
continueWith拿到的返回结果,没有绑定到 UI 更新的流程里,等于异步任务跑完的时候,更新 TextView 的代码早就执行过了,就算拿到了订单数据,也不会刷到页面上。
- 异步时序完全搞反了:Firebase Callable 的网络请求是后台异步跑的,原代码发起
修正后的可运行代码
Firebase Cloud Function 修正版
const functions = require("firebase-functions"); exports.order = functions.https.onCall(async (amount, context) => { const Ippopay = require('node-ippopay'); const ippopay_instance = new Ippopay({ public_key: 'YOUR_PUBLIC_KEY', secret_key: 'YOUR_SECRET_KEY', }); // 将回调风格的接口封装为Promise,让云函数可以等待异步结果 const createOrderPromise = new Promise((resolve, reject) => { ippopay_instance.createOrder({ amount: amount, currency: 'DOLLAR', payment_modes: "cc,dc,nb,cheque", customer: { name: "Test", email: "test@gmail.com", phone: { country_code: "42", national_number: "4376543210" } } }, function (err, data) { if (err) { // 接口报错时抛出标准的云函数错误,同步给客户端 reject(new functions.https.HttpsError('internal', '支付订单创建失败', err)); return; } resolve(data); }); }); // 等待异步订单创建完成,把结果作为云函数返回值 const orderResult = await createOrderPromise; return orderResult; });
Android 客户端修正版
pay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("PAY Button clicked", "yes"); mFunctions = FirebaseFunctions.getInstance("us-central1"); mFunctions.getHttpsCallable("order") .call(5) .addOnCompleteListener(task -> { // 所有UI更新逻辑必须放到异步任务完成的回调里执行 if (task.isSuccessful()) { // 成功拿到云函数返回的订单数据 HttpsCallableResult result = task.getResult(); data = result.getData().toString(); order_data.setText(data); onPaymentClick(); } else { // 捕获云函数返回的错误,方便排查问题 Exception e = task.getException(); order_data.setText("请求失败:" + e.getMessage()); } }); } });
内容的提问来源于stack exchange,提问作者Samantha D'Souza
相关产品推荐
相关产品推荐

