Accepting payments in Flutter Web - flutter

I am creating an application in Flutter Web that needs to collect payment information to create subscription charges. My plan was to use Stripe to do this, however, after making all the necessary methods for Stripe, I found that Stripe only accepts card data through Stripe Elements. Upon further research, I saw that essentially all payment platforms do this to maintain PCI compliance.
Is there any method of embedding Stripe elements(or any equivalent) into my application or is there an easier method of accepting payments with Flutter Web?

There's an unofficial Flutter Stripe package that might be what you're after: https://pub.dev/packages/stripe_payment

There's a new package called stripe_sdk, that appears to have Web support. I haven't tried it yet, but it says Web support in the description and has a web demo aswell :)
Also the old packages for mobile won't work for web, because they rely on WebView, which is not supported (and wouldn't make much sense) on web.

In case you're using Firebase as a backend, there's a stripe payments extension you can install in Firebase which makes it easy. How it works is you add a checkout_session in to a user collection and keep listening on the document. Stripe extension will update the document with a unique payments url and we just open that URL in a new tab to make the payment in the tab. We're using it in our web app, and it's working.
Something like :
buyProduct(Product pd) async {
setState(() {
loadingPayment = true;
});
String userUid = FirebaseAuth.instance.currentUser!.uid;
var docRef = await FirebaseFirestore.instance
.collection('users')
.doc(userUid)
.collection('checkout_sessions')
.add({
'price': pd.priceId,
'quantity': pd.quantity,
'mode': 'payment',
'success_url': 'https://yourwebsite/purchase-complete',
'cancel_url': 'https://yourwebsite/payment-cancelled',
});
docRef.snapshots().listen(
(ds) async {
if (ds.exists) {
//check any error
var error;
try {
error = ds.get('error');
} catch (e) {
error = null;
}
if (error != null) {
print(error);
} else {
String url = ds.data()!.containsKey('url') ? ds.get('url') : '';
if (url != '') {
//open the url in a new tab
if (!isStripeUrlOpen) {
isStripeUrlOpen = true;
setState(
() {
loadingPayment = false;
},
);
launchUrl(Uri.parse(url));
}
}
}
}
}
},
);
}

Related

Callback with Stripe and Paymentsheet

I am implementing the Paymentsheet method of Stripe in my application, but i can't find a callback or something else to know if the payment has been confirmed or there have been problems.
Is this information available with Paymentsheet? If not, how can i pay using stripe sdk and receive a callback of the call
You need to use Stripe webhooks to be notified when the payment succeeds. More specifically you should listen to the payment_intent.succeeded event. You can learn more about this in this doc.
I tried with try and catch only because using webhook it tooks some time for our mobile UI. Though, Webhook is the best option. Whatever I did here is some time of patch.
Future<void> _presentPaymentSheet(
BuildContext context, String? clientSecret) async {
try {
await Stripe.instance.presentPaymentSheet();
// ==> Here, I assume payment success
state = NetworkState.success;
} on Exception catch (stripeException) {
if (stripeException is StripeException) {
state = NetworkState.error;
if (stripeException.error.code == FailureCode.Canceled) {
context.showSnackBar(AppStrings.errorFromStripe +
(stripeException.error.localizedMessage ?? ''));
context.pop();
} else {
debugLog('Error7: $stripeException');
context.showSnackBar(AppStrings.errorFromStripe +
(stripeException.error.localizedMessage ?? ''));
}
}
}
}

Calendar clientViaUserConsent it gives me Authorization Error while creating event

clientViaUserConsent opens URL in browser but it said invalid request. this URL is generated internally from lib. I had double-checked my ClientId for both platforms but still face issues for getting AuthClient for create a calendar event.
I used the below packages to create events in the google calender.
googleapis: ^8.1.0
googleapis_auth: ^1.3.0
static final androidClientId = ClientId('xxxxxxxx.apps.googleusercontent.com');
static final iOSClientId = ClientId('xxxxxxx.apps.googleusercontent.com');
final _clientID = Platform.isAndroid ? EventProvider.androidClientId : EventProvider.iOSClientId;
final _scopes = [CalendarApi.calendarScope];
clientViaUserConsent(_clientID, _scopes, prompt).then((AuthClient client) {
var calendar = CalendarApi(client);
}
void prompt(String url) async {
print(" => $url");
if (await canLaunch(url)) {
await launch(URL);
} else {
throw 'Could not launch $url';
}
}
I am referring to this article for creating an event in google calendar.
https://blog.codemagic.io/google-meet-events-in-flutter/
https://medium.com/flutter-community/flutter-use-google-calendar-api-adding-the-events-to-calendar-3d8fcb008493
You are seeing that error because the app hasn't been verified. If you are the app developer I advise you to check the App Verification FAQ to learn more about the verification steps. If you aren't the developer, you could try to enable the less secure app access but please be mindful of the consequences:
Less secure apps can make it easier for hackers to get in to your account, so blocking sign-ins from these apps helps keep your account safe.

How to send a message directly from my Flutter web application to WhatsApp Business?

I am building an flutter web application that has to be able to send message on specific WhatsApp Business number and WhatsApp number. What exactly am I supposed to do? If the user's device has either WhatsApp or WhatsApp Business, he opens it. But my problem is that if user's device has both WhatsApp and WhatsApp business, I want one to open on one condition.
var whatsappURlAndroid = "https://wa.me/$whatsappNumber/?text=Hi";
var whatappURLIos ="https://wa.me/$whatsappNumber?text=${Uri.parse("hello")}";
var webWhatsapp= "https://web.whatsapp.com/send?phone=$whatsappNumber&text=Hello";
if (defaultTargetPlatform == TargetPlatform.iOS) {
await launch(whatappURLIos, forceSafariVC: false);
}else if(defaultTargetPlatform == TargetPlatform.android){
await launch(whatsappURlAndroid);
}
else{
await launch(webWhatsapp);
}
FocusManager.instance.primaryFocus?.unfocus();
var whatsappUrl = "whatsapp://send?phone=${_countryCodeController.text +
_phoneController.text}" +
"&text=${Uri.encodeComponent(_messageController.text)}";
try {
launch(whatsappUrl);
} catch (e) {
// To handle error and display error message:
Helper.errorSnackBar(
context: context, message: "Unable to open whatsapp");
}

can't load iap products in local, it waits forever

I'm using the official in_app_purchase plugin, version ^1.0.4, and I'm following the official guide from Google insert my first iap (https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases#0).
My consumable iap product is active on Play console with name "pacchetto_25", I've already submitted to the alpha channel my app and is accepted, the tester email is correctly configured in the Tester Group and in Licence Testing.
Now I'm trying to load the iap products in my app, the code is the same of the guide:
Future<void> loadPurchases() async {
final available = await _iap.isAvailable();
if (!available) {
print("STORE NOT AVAILABLE");
return;
} else {
print("STORE AVAILABLE");
const ids = <String>{
"pacchetto_25",
};
final response = await _iap.queryProductDetails(ids);
response.notFoundIDs.forEach((element) {
print('Purchase $element not found');
});
response.productDetails.forEach((element) {
print("Purchase $element found");
});
// products =
// response.productDetails.map((e) => PurchasableProduct(e)).toList();
}
}
In my console I have the "STORE AVAILABLE" message, but then nothing else. If I put same debug point it does not stops on them, this problem appear after this line:
final response = await _iap.queryProductDetails(ids);
Do someone know what's happening? I've no errors in my console and the code after loadPurchases() is not executed, it's like is waiting forever... Any ideas?
Solved! If you have the same issue DON'T put
implementation("com.android.billingclient:billing:4.0.0")
in your build.gradle

in_app_purchases using flutter

I am trying to create an application that can handle In App Purchases Using Flutter.I am using the in_app_purchase 0.2.1 plugin .I have managed to setup my product on google play developer console as required but however when try to retrieve it from the application i am able to connect to the store successfully but i am not able to retrieve my product ,it always shows up as product not found.
I have followed a this tutorial https://joebirch.co/2019/05/31/adding-in-app-purchases-to-flutter-apps/ and also looked at the package documentation https://pub.dev/packages/in_app_purchase.
My google play setup for the product is shown below
google play console setup
google play console setup2
The function i am using is shown below.
Future<List<ProductDetails>> retrieveProducts() async {
final bool available = await InAppPurchaseConnection.instance.isAvailable();
if (!available) {
// Handle store not available
print("Store Temporarily Unavailable");
return null;
} else {
print("Store Temporarily Available");
const Set<String> _kIds = {'airtime123'};
final ProductDetailsResponse response =
await InAppPurchaseConnection.instance.queryProductDetails(_kIds);
if (response.notFoundIDs.isNotEmpty) {
print("product not found");
print(response.notFoundIDs[0]);
return null;
}
print("product found");
return response.productDetails;
}
}
This is the result i get
I/flutter ( 7254): Store Temporarily Available
I/flutter ( 7254): product not found
I/flutter ( 7254): airtime123
You need to use a reserved SKU for the test: android.test.purchased
const Set<String> _kIds = {'android.test.purchased'};
final ProductDetailsResponse response =
await InAppPurchaseConnection.instance.queryProductDetails(_kIds);