Firebase functions callable "isn't referenced" when used in Flutter
I've deployed a HTTPS function on firebase and I try to call it from my Flutter app, but nothing happens.
I got the following error in my code:
The declaration 'paymentRequest' isn't referenced. Try removing the declaration of 'paymentRequest'.
Here is my successfully deployed function in Firebase:
// Generate Payment URL
exports.paymentRequest = functions.https.onCall(async (data, context) => {
const clientAccessToken = data.clientAccessToken;
const recipientIban = data.recipientIban;
const recipientName = data.recipientName;
const paymentDescription = data.paymentDescription;
const paymentReference = data.paymentReference;
const productPrice = parseInt(data.productPrice);
const jsonData = {
"destinations": [
{
"accountNumber": recipientIban,
"type": "iban"
}
],
"amount": productPrice,
"currency": "EUR",
"market": "FR",
"recipientName": recipientName,
"sourceMessage": paymentDescription,
"remittanceInformation": {
"type": "UNSTRUCTURED",
"value": paymentReference
},
"paymentScheme": "SEPA_INSTANT_CREDIT_TRANSFER"
};
axios({
method: "post",
url: "https://myapiendpoint.com/api/v1/requests",
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${clientAccessToken}`,},
data: jsonData,
})
.then(function (response) {
//handle success
console.log(response.data);
})
.catch(function (response) {
//handle error
console.log(response);
});
return response.data;
})
And here is an extract of my flutter code:
import 'package:cloud_functions/cloud_functions.dart';
...visual stuff...
child: ElevatedButton(
child: const Text('Submit'),
onPressed: () {
Future<void> paymentRequest(String message) async { // This is where I have an error
HttpsCallable callable = FirebaseFunctions.instance
.httpsCallable('paymentRequest');
final resp = await callable.call(
<String, dynamic>{
'clientAccessToken':
'a_valid_token',
'recipientIban': ibanController,
'recipientName': nameController,
'paymentDescription': descriptionController,
'paymentReference': referenceController,
'productPrice': productPriceController
},
);
print("result: ${resp.data}");
}
showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Retrieve the text the that user has entered by using the
// TextEditingController.
title: Text('Success!'),
// content: Text(productPriceController.text),
content: Text(
'The product page has been successfully updated.'),
actions: [
Center(
child: ElevatedButton(
style: ElevatedButton.styleFrom(),
onPressed: () async {
// Navigator.pushReplacementNamed(
// context, '/');
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => HomeScreen(
productPrice:
productPriceController
.text)));
},
child: Text('Go to Product page'),
),
),
],
);
},
);
},
)
Any ideas?
Thanks!
Solution 1:
Instead of declaring a new function inside a callback
onTap: () {
Future<void> someFunctionDeclaration() async {
// your cloud functions call and consequent showDialog
}
}
just create a seperate function inside the widget (or other file)
class X extends StatelessWidget {
...
@override
Widget build(BuildContext context) {
return Widget(
// visual stuff
ElevatedButton(
onTap: () async {
await someFunction(messageVariable);
showDialog...
}
),
// more visual stuff
// end of build method
}
Future<void> someFunction(String message) async {
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('paymentRequest');
final resp = await callable.call(
<String, dynamic>{
'clientAccessToken': 'a_valid_token',
'recipientIban': ibanController,
'recipientName': nameController,
'paymentDescription': descriptionController,
'paymentReference': referenceController,
'productPrice': productPriceController
},
);
}
}
This also has the advantage of making your code cleaner. It's easier to read something like processPayment(data)
than a whole segment of business logic in the view
code.