How to send and verify OTP using cloud function in flutter? - flutter

I have API to send and verify otp code. I need to link that API to my flutter app using Firebase clod function. How is it possible Please help ?

Setup firebase cloud function here
Your js code be like
exports.sendOtp = functions.https.onCall((request, response) => {
const options = JSON.stringify({
mobile: request.text,
});
const headers = {
"Authorization": "Bearer xxxxxxxxxxxxxxxxxxxxxxx”,
};
const res = axios.post(“url”, options, {headers: headers}).then((response) => {
console.log(response);
return response;
});
return res.statusCode;
});
Your service code be like
Future<void> sendOtp(String mobile) async {
HttpsCallable callable =
FirebaseFunctions.instance.httpsCallable('sendOtp');
final resp = await callable.call(<String, dynamic>{
'text': mobile,
});
}

Related

Flutter Request failed Google Pay live mode using Stripe Payment

Google pay is completely working on Test mode but after set the live secret key in "v1/payment_intents" in this API so it's not working and getting the below error. I'm using the Stripe plugin.
Future<void> startGooglePay() async {
final googlePaySupported = await Stripe.instance.isGooglePaySupported(IsGooglePaySupportedParams(testEnv:
false));
if (googlePaySupported) {
try {
// 1. fetch Intent Client Secret from backend
final response = await fetchPaymentIntentClientSecret();
print(response);
final clientSecret = response['client_secret'];
// 2.present google pay sheet
await Stripe.instance.initGooglePay(GooglePayInitParams( merchantName: "Test Name",
countryCode: 'US',testEnv: false));
await Stripe.instance.presentGooglePay(PresentGooglePayParams(clientSecret: clientSecret,currencyCode: "GBP"),);
await Stripe.instance.initPaymentSheet(paymentSheetParameters: SetupPaymentSheetParameters(
googlePay: PaymentSheetGooglePay(merchantCountryCode: 'US'),
paymentIntentClientSecret: response['client_secret'],
setupIntentClientSecret:response['client_secret'],
customerEphemeralKeySecret: response['client_secret'],
customerId:PLPrefrence.getPrefValue(key: PLPrefrence.user_code).toString()
));
await Stripe.instance.retrievePaymentIntent(response['client_secret']).then((value){
print(value.id);
print(value.status);
print(value.confirmationMethod.name);
});
} catch (e) {
print('ErrorStripePrint : ${e}');
errorDialog(errorMessage: "$e");
}
} else {
errorDialog(errorMessage: "Google pay is not supported on this device");
}
}
Now here is the API call for payment_intents API
Future<Map<String, dynamic>> fetchPaymentIntentClientSecret() async {
final url = Uri.parse('https://api.stripe.com/v1/payment_intents');
Map<String, dynamic> body = {
'amount':calculateAmount(amount: _plController.isUseWalletbalance.value ?
_plController.processedAmount.value : widget.grandTotal.toString()).toString(),
'currency': "GBP",
'payment_method_types[]': 'card',
};
final response = await http.post(
url,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ${PLKeys.stripeSK_Live}',
},
body: body,
);
return json.decode(response.body);
}
if I set the testEnv true and test secret key in so it's working but set testEnv false and set stripe live mode secret key so it's not working and getting issue as upload image above.
Error Image:-

How to create a post request in flutter - GetConnect

I am creating a flutter app using GetX, for making server connections I am using GetConnect, I successfully integrated the Get Request but I am unable to integrate Post Request
Here is the piece of code:
const _baseUrl = 'https://support.instagram.com/'; // Dummy api url and key
const Map<String, String> _mapHeaders = {
"ISG-API": "ZMWFDK83NMDF7NM5DF23FI0DBUJ"
};
class ApiService extends GetConnect {
Future<TicketReply> submitTicketReply(String ticketId, String tktreply) async {
String apiUrl = '${_baseUrl}/supportreply';
var body = {
'tktid': ticketId,
'tktreply': tktreply,
};
final response = await post(
apiUrl,
body,
headers: _mapHeaders,
);
print('response: ${response.body}');
if (response.statusCode == 200) {
return TicketReply.fromJson(response.body);
} else {
return Future.error(response.statusText!);
}
}
}
Kindly guide me how to make a successful post request using getconnect
You should add the decoder to the request like so
await post(
apiUrl,
body,
headers: _mapHeaders,
decoder: (resbody) => TicketReply.fromJson(resbody),
);

How to pass data to cloud function file in flutter

I am new to flutter and I have just created app that accepts payments from user using flutter_stripe: ^2.1.0 plugin. The amount in cloud function file index.js is fixed but I want to pass the amount that is calculated dynamically. Here is my code.
Future<void> makePayment() async {
final url = Uri.parse(
'https://us-central1-carwashapp-376b6.cloudfunctions.net/stripePayment');
final response =
await http.get(url, headers: {"Content-Type": "application/json"});
paymentIntentData = json.decode(response.body);
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntentData['paymentIntent'],
applePay: true,
googlePay: true,
style: ThemeMode.light,
merchantCountryCode: 'US',
merchantDisplayName: 'Kleen My Car',
),
);
setState(() {});
displayPaymentSheet();
}
Future<void> displayPaymentSheet() async {
try {
await Stripe.instance.presentPaymentSheet(
parameters: PresentPaymentSheetParameters(
clientSecret: paymentIntentData['paymentIntent'],
confirmPayment: true));
setState(() {
paymentIntentData = null;
});
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Payment succeeded')));
} catch (e) {
print('error error error');
}
}
and here is my index.js file's code
const functions = require("firebase-functions");
const stripe = require("stripe")(functions.config().stripe.testkey);
exports.stripePayment = functions.https.onRequest(async (req, res) => {
const paymentIntent = await stripe.paymentIntents.create(
{
amount: 120,
currency: "USD",
},
function (err, paymentIntent) {
if (err != null) {
console.log(err);
} else {
res.json({
paymentIntent: paymentIntent.client_secret,
});
}
}
);
});
Any kind of help is much appreciated. Thank you so much!
You need to adapt this line:
final response = await http.get(url, headers: {"Content-Type": "application/json"});
(Firstly, it makes no sense to give a content type on a GET, as GETs don't have any content. Remove that header.)
You could change to a POST and add the amount as a parameter, or leave it as a GET and add the amount to the URL.
With a POST, add (for example) body: {'amount': amount.toString()}
With a GET, add it to the URL, as follows:
final uri = Uri.https('us-central1-carwashapp-376b6.cloudfunctions.net', '/stripepayment', {'amount': amount.toString()});
In your cloud function access amount from the req. (For example, in the GET example, it would be req.query.amount as string.)
We also pass up other parameters like email, unique order id (to be used as the idempotency key), etc.
in index.js file change
const paymentIntent = await stripe.paymentIntents.create(
{
amount: 120,
currency: "USD",
},
to
const paymentIntent = await stripe.paymentIntents.create(
{
amount: req.query.amount,
currency: req.query.currency,
},
and deploy your function.
after that, in makepayment function, change your URL to
https://us-central1-carwashapp-376b6.cloudfunctions.net/stripePayment?amount=$amount&currency=$currency.
In this way, you can pass different amounts every time by changing the value of $amount variable in the URL.

How to have Similar functionality as Server-Sent-Event / EventSource functionality in Flutter?

I have a web developer background, just a beginner in Flutter and Dart.
For a project, I need to implement Server-Sent-Event / EventSource functionality in Flutter.
I have searched for options like dart:http EventSource constructor and Flutter StreamBuilder but I have not found a working example with API.
Can you give me some examples where the Flutter app can listen to an API?
This is what do in Web development.
// client side
const eventSource = new EventSource(`/eventSource/${xyz}`)
eventSource.onmessage = function(e) {
const data = JSON.parse(e.data)
console.log(e)
}
// server side
router.get('/eventSource/:id', (req, res) => {
const headers = {
'Content-Type': 'text/event-stream',
'Connection': 'keep-alive',
'Cache-Control': 'no-cache'
}
res.writeHead(200, headers)
const data = `data: ${JSON.stringify(someData)}\n\n`
setInterval(() => {
x.write(data)
}, 3000)
req.on('close', () => {})
})
This code maybe helpful
var _client;
var _streamResponse;
Future<dynamic> streamFiles() async {
_client = http.Client();
final url = 'url';
var headers = {};
final req = http.Request('GET', Uri.parse(url));
req.headers.addAll(headers);
final res = await _client.send(req);
_streamResponse = res.stream.toStringStream().listen((value) {
print(json.decode(value));
});
}
#override
void dispose() {
if (_streamResponse != null) _streamResponse.cancel();
if (_client != null) _client.close();
super.dispose();
}

How to get the token from firebase_auth

I'd like to get the auth token from firebase (email and password auth) to authenticate in my firebase cloud function. It seems like the functions getIdToken() and getToken() are both not working for firebase_auth package.
is there an other function or is there even a better idea to make sure only authenticated users can trigger the cloud functions?
var token = await FirebaseAuth.instance.currentUser.getIdToken();
var response = await httpClient.get(url,headers: {'Authorization':"Bearer $token"});
I agree with #Doug on this one - callable wraps this for you and will be easier -, but my use case required me to make HTTPS calls (onRequest in Functions). Also, I think you're just in the correct path - but you're possibly not checking it in your Cloud Functions.
In your app, you'll call:
_httpsCall() async {
// Fetch the currentUser, and then get its id token
final user = await FirebaseAuth.instance.currentUser();
final idToken = await user.getIdToken();
final token = idToken.token;
// Create authorization header
final header = { "authorization": 'Bearer $token' };
get("http://YOUR_PROJECT_BASE_URL/httpsFunction", headers: header)
.then((response) {
final status = response.statusCode;
print('STATUS CODE: $status');
})
.catchError((e) {
print(e);
});
}
In your function, you'll check for the token:
export const httpsFunction = functions.https.onRequest((request, response) => {
const authorization = request.header("authorization")
if (authorization) {
const idToken = authorization.split('Bearer ')[1]
if (!idToken) {
response.status(400).send({ response: "Unauthenticated request!" })
return
}
return admin.auth().verifyIdToken(idToken)
.then(decodedToken => {
// You can check for your custom claims here as well
response.status(200).send({ response: "Authenticated request!" })
})
.catch(err => {
response.status(400).send({ response: "Unauthenticated request!" })
})
}
response.status(400).send({ response: "Unauthenticated request!" })
})
Keep in mind:
If I'm not mistaken, those tokens are valid for 1 hour, if you are going to store them somewhere, just be aware of this. I've tested locally and it takes around 200~500ms - every time - to get only the id token, which in most cases are not that big of overhead - but is significant.
It's going to be easiest for you to use a callable function, since that lets you:
Automatically send the current user's uid in the request.
Know very easily on the function side if a UID was provided in the request, and refuse service if none was provided.
The flutter plugin is here.
You should be able to do the equivalent work yourself, though, since callable functions are just a wrapper around normal HTTP connections. It's possible for you to get the ID token of the logged in user.
import 'package:firebase_messaging/firebase_messaging.dart';
.
.
.
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
#override
Future<void> initState() {
super.initState();
_firebaseMessaging.getToken().then((token) {
assert(token != null);
print("teken is: " + token);
});
}
Get your token from firebaseAuth and put in a string.
Future<Details> getDetails() async {
String bearer = await FirebaseAuth.instance.currentUser!.getIdToken();
print("Bearer: " + bearer.toString());
String token = "Bearer ${bearer}";
var apiUrl = Uri.parse('Your url here');
final response = await http.get(apiUrl, headers: {
'Authorization' : '${token}'
});
final responseJson = jsonDecode(response.body);
return Details.fromJson(responseJson);
}