Issue is in displaying card in stripe payment - flutter

I want to intigrate stripe payment but i got this error
Instance of 'StripeConfigException
Also my when i click on pay button it is not showing any type of card.
I want to print jsonresponse["emphermalKey"] and jsonresponse["customer"] but these show null value .
Please solve my issue i am stuck in stripe payment for couple of days
Here is my stripe log which shoes null value
{
"customer": null,
"description": null,
"invoice": null,
"last_payment_error": null,
"latest_charge": null,
"next_action": null,
"on_behalf_of": null,
"payment_method": null,
"payment_method_options": {
"card": {
"installments": null,
"mandate_options": null,
"network": null,
"request_three_d_secure": "automatic"
}
"processing": null,
"review": null,
"setup_future_usage": null,
"shipping": null,
"source": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "requires_payment_method",
"transfer_data": null,
"transfer_group": null
}
my code
Center(
child: ElevatedButton(
onPressed: () {
intpayment(email: "email,amount: 50.0);
},
child: Text("Pay20\$"),
),
),
Function
Future<void> intpayment(
{required String email, required double amount})async{
try{
final response= await http.post(Uri.parse("https://api.stripe.com/v1/payment_intents")
,body:{
"receipt_email": email,
"amount": amount.toInt().toString(),
"currency": "usd"
},
headers: {
'Authorization': 'Bearer ' + 'key',
'Content-Type': 'application/x-www-form-urlencoded'
}
);
final jsonresponse=jsonDecode(response.body); Stripe.instance.initPaymentSheet(paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: jsonresponse['paymentIntent'],
merchantDisplayName: 'Zohaib',
customerId: jsonresponse['customer'],
customerEphemeralKeySecret: jsonresponse['ephemeralKey'],
));
await Stripe.instance.presentPaymentSheet();
Fluttertoast.showToast(
msg: "payment successfully",
);
}
catch(e){
if (e is StripeException) {
Fluttertoast.showToast(
msg: "Stripe error $e",
);
}
Fluttertoast.showToast(
msg: "$e",
toastLength: Toast.LENGTH_SHORT, );
}
}

Related

Issue in displaying card in stripe payment intigration

I want to intigrate stripe payment but i got this error Instance of 'StripeConfigException Also my when i click on pay button it is not showing any type of card. I want to print jsonresponse["emphermalKey"] and jsonresponse["customer"] but these show null value.I also put api key correctly . Please solve my issue i am stuck in stripe payment for couple of days Here is my stripe log which shoes null value.
{
"customer": null,
"description": null,
"invoice": null,
"last_payment_error": null,
"latest_charge": null,
"next_action": null,
"on_behalf_of": null,
"payment_method": null,
"payment_method_options": {
"card": {
"installments": null,
"mandate_options": null,
"network": null,
"request_three_d_secure": "automatic"
}
"processing": null,
"review": null,
"setup_future_usage": null,
"shipping": null,
"source": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "requires_payment_method",
"transfer_data": null,
"transfer_group": null
}
my code
Center(
child: ElevatedButton(
onPressed: () {
intpayment(email: "email,amount: 50.0);
},
child: Text("Pay20\$"),
),
),
Function
Future<void> intpayment(
{required String email, required double amount})async{
try{
final response= await http.post(Uri.parse("https://api.stripe.com/v1/payment_intents")
,body:{
"receipt_email": email,
"amount": amount.toInt().toString(),
"currency": "usd"
},
headers: {
'Authorization': 'Bearer ' + 'key',
'Content-Type': 'application/x-www-form-urlencoded'
}
);
final jsonresponse=jsonDecode(response.body); Stripe.instance.initPaymentSheet(paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: jsonresponse['paymentIntent'],
merchantDisplayName: 'Zohaib',
customerId: jsonresponse['customer'],
customerEphemeralKeySecret: jsonresponse['ephemeralKey'],
));
await Stripe.instance.presentPaymentSheet();
Fluttertoast.showToast(
msg: "payment successfully",
);
}
catch(e){
if (e is StripeException) {
Fluttertoast.showToast(
msg: "Stripe error $e",
);
}
Fluttertoast.showToast(
msg: "$e",
toastLength: Toast.LENGTH_SHORT, );
}
}
I think issue in this line when I comment out this the error remove but card is not displying
await Stripe.instance.presentPaymentSheet();
If you don't have any value in jsonresponse it means you backend hasn't been able to return them, and mostly because it didn't have the correct Secret Key or having some issue sending Stripe API itself.
The fastest way to isolate the issue is looking at your backend log, or your Stripe Request Logs https://dashboard.stripe.com/test/logs and find the specific call from your backend -> Stripe.

Why not displaying card

I want to intigrate stripe payment but i got this error
** FlowController must be successfully initialized using configureWithPaymentIntent() or configureWithSetupIntent() before calling presentPaymentOptions()**
How solve this error also it is not displaying any card
Center(
child: ElevatedButton(
onPressed: () {
intpayment(email: "email,amount: 50.0);
},
child: Text("Pay20\$"),
),
),
Future<void> intpayment(
{required String email, required double amount})async{
try{
final response= await http.post(Uri.parse("https://api.stripe.com/v1/payment_intents")
,body:{
"receipt_email": email,
"amount": amount.toInt().toString(),
"currency": "usd"
},
headers: {
'Authorization': 'Bearer ' + 'key',
'Content-Type': 'application/x-www-form-urlencoded'
}
);
final jsonresponse=jsonDecode(response.body); Stripe.instance.initPaymentSheet(paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: jsonresponse['paymentIntent'],
merchantDisplayName: 'Zohaib',
));
await Stripe.instance.presentPaymentSheet();
Fluttertoast.showToast(
msg: "payment successfully",
);
}
catch(e){
if (e is StripeException) {
Fluttertoast.showToast(
msg: "Stripe error $e",
);
}
Fluttertoast.showToast(
msg: "$e",
toastLength: Toast.LENGTH_SHORT, );
}
}
You need to create the PaymentIntent on the server-side and not within your flutter app.
final response= await http.post(Uri.parse("https://api.stripe.com/v1/payment_intents")
,body:{
"receipt_email": email,
"amount": amount.toInt().toString(),
"currency": "usd"
},
headers: {
'Authorization': 'Bearer ' + 'key',
'Content-Type': 'application/x-www-form-urlencoded'
}
);
Instead of calling the Stripe API directly as you did in the code above, you should call your own API and generate a Payment Intent and just send the client_secret to your flutter App, otherwise you would be exposing your secret key and thus giving access to your data. This is described here.
Once you do this server-side part the rest is explained here.

Stripe error the customer has not entered their payment method in flutter

I have integrated flutter_stripe 2.0.1 plugins in my flutter application using Firebase CLI. getting a successful response of paymentIntent from firebase provided URL. But in the Stripe dashboard payment status is Incomplete.
Below is my node.js code
index.js file
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: 1,
currency: 'usd'
},
function(err, paymentIntent) {
if(err != null){
console.log(err);
} else {
res.json({
paymentIntent: paymentIntent.client_secret,
})
}
}
)
});
Below is my flutter code
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Stripe.publishableKey = stripePublishableKey;
Stripe.merchantIdentifier = 'merchant.flutter.stripe.test'; //any string works
await Stripe.instance.applySettings();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DashboradPage(),
);
}
}
class DashboradPage extends StatefulWidget {
const DashboradPage({Key? key}) : super(key: key);
#override
_DashboradPageState createState() => _DashboradPageState();
}
class _DashboradPageState extends State<DashboradPage> {
Map<String, dynamic>? paymentIntentData;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Stripe Examples'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
makePayment();
},
child: Text('Pay Amount'),
),
),
);
}
Future<void> makePayment() async {
final url = Uri.parse(
'https://us-central1-stripeflutterdemo.cloudfunctions.net/stripePayment');
final header = {'Content-Type': 'application/json'};
try {
final response = await http.get(url, headers: header);
paymentIntentData = json.decode(response.body);
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntentData?['paymentIntent'] ?? '',
applePay: true,
googlePay: true,
style: ThemeMode.light,
merchantCountryCode: 'US',
merchantDisplayName: 'Flutter Stripe Store Demo',
));
setState(() {});
displayPaymentSheet();
} catch (e) {
print(e);
displaySnackbar(e.toString());
}
}
Future<void> displayPaymentSheet() async {
try {
await Stripe.instance.presentPaymentSheet();
// await Stripe.instance.presentPaymentSheet(
// parameters: PresentPaymentSheetParameters(
// clientSecret: paymentIntentData?['paymentIntent'] ?? '',
// confirmPayment: true,
// ),
// );
setState(() {
paymentIntentData = null;
});
displaySnackbar('Payment succesfully completed');
} catch (e) {
print(e);
displaySnackbar(e.toString());
}
}
void displaySnackbar(String msg) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(msg),
),
);
}
}
Below is the postman response of URL mentioned in makePayment()
I have used payment sheet, when I clicked on the Pay button it is redirecting to webview (Authentication completed) but in the Stripe dashboard payment status is Incomplete.
Stripe Dashboard Payment Event data
PaymentIntent status:requires_payment_method,
PaymentIntent status:requires_action
From Stripe
payment_intent.payment_failed
View event detail
Event data
{
"id": "pi_3JpZh7SIKwX0CSUQ0sUoM9wK",
"object": "payment_intent",
"last_payment_error": {
"message": "As per Indian regulations, export transactions require a description. More info here: https://stripe.com/docs/india-exports",
"param": "description",
"payment_method": {
"id": "pm_1JpZijSIKwX0CSUQ7u91wths",
"object": "payment_method",
"billing_details": {
"address": {
"city": null,
"country": "US",
"line1": null,
"line2": null,
"postal_code": "45612",
"state": null
},
"email": null,
"name": null,
"phone": null
},
"card": {
"brand": "visa",
"checks": {
"address_line1_check": null,
"address_postal_code_check": "unchecked",
"cvc_check": "unchecked"
},
"country": "US",
"exp_month": 4,
"exp_year": 2044,
"fingerprint": "EK9VAoccqqCLBqQk",
"funding": "credit",
"generated_from": null,
"last4": "4242",
"networks": {
"available": [
"visa"
],
"preferred": null
},
"three_d_secure_usage": {
"supported": true
},
"wallet": null
},
"created": 1635431806,
"customer": null,
"livemode": false,
"metadata": {
},
"type": "card"
},
"type": "invalid_request_error"
},
"livemode": false,
"next_action": null,
"status": "requires_payment_method",
"amount": 1,
"amount_capturable": 0,
"amount_received": 0,
"application": null,
"application_fee_amount": null,
"canceled_at": null,
"cancellation_reason": null,
"capture_method": "automatic",
"charges": {
"object": "list",
"data": [
],
"has_more": false,
"total_count": 0,
"url": "/v1/charges?payment_intent=pi_3JpZh7SIKwX0CSUQ0sUoM9wK"
},
"client_secret": "pi_3JpZh7SIKwX0CSUQ0sUoM9wK_secret_oVhK5CmrcHjImvFMyoo51GCXy",
"confirmation_method": "automatic",
"created": 1635431705,
"currency": "usd",
"customer": null,
"description": null,
"invoice": null,
"metadata": {
},
"on_behalf_of": null,
"payment_method": null,
"payment_method_options": {
"card": {
"installments": null,
"network": null,
"request_three_d_secure": "automatic"
}
},
"payment_method_types": [
"card"
],
"receipt_email": null,
"review": null,
"setup_future_usage": "off_session",
"shipping": null,
"source": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"transfer_data": null,
"transfer_group": null
}
Below is the iPhone screenshot
According to the Stripe documentation, the required_payment_method message as a status means you have not attached a payment method to your payment intent:
When the PaymentIntent is created, it has a status of requires_payment_method until a payment method is attached.
There is an official document explaining how to integrate Stripe payments with your Firebase backend. It provides all the required code and steps to properly set up payments with Stripe. In the sample code inside the index.js file, they include additional objects when creating the payment intent with stripe.paymentIntents.create()
const payment = await stripe.paymentIntents.create(
{
amount,
currency,
customer,
Payment_method, //payment method when creating the payment intent
off_session: false,
confirm: true,
confirmation_method: 'manual',
},
{ idempotencyKey }
);
Since your sample is missing the payment method, it could explain the error you are receiving, as the PaymentIntent is being created without a payment method. I recommend following the guide to cover all the required steps to avoid further errors that might be present. You can also see the full sample code, which is documented and can be customized for your use case and the flutter_stripe library.

How to fix type 'List<dynamic>' is not a subtype of type 'String'

Currently I am getting this kind of issue from my code. I was trying to solved this problem continuously. But could not fund the solution of this problem.
Json Codes
{
"id": 22,
"client_need_id": 46,
"clientNeed": {
"id": 46,
"client_id": 29,
"perpose": "Pooja",
"details": "Test",
"when": "2020-08-28 20:11",
"for": null,
"accepted_by": 10,
"name": "Sfgdsa",
"mobile": "567896789",
"email": "sdnsd#asd.com",
"org_name": "Buii",
"address": "Tata",
"city": "Kolkata",
"state": "West Bengal",
"pincode": "789009",
"country": "India",
"latitude": null,
"longitude": null,
"client_ip": null,
"device": null,
"created_at": "2020-08-23T14:40:06.000000Z",
"updated_at": "2020-09-02T18:07:40.000000Z"
},
"quote_details": null,
"quote_amount": null,
"isCalled": 0,
"isChecked": 0,
"isAccept": 1,
"isGoing": 0,
"checkIn": "2020-09-03 02:00:00",
"checkOut": "2020-09-03 02:00:15",
"pandit_id": 10,
"pandit": {
"id": 10,
"name": "Ajay Roy",
"mobile": "8013138886",
"sms_token": null,
"mobile_verified_at": null,
"email": "ajay#abc.com",
"email_token": null,
"email_verified_at": null,
"password": "5f4dcc3b5aa765d61d8327deb882cf99",
"remember_token": null,
"avatar": null,
"address": "dum dum cantonment",
"city": "Kolkata",
"state": "West Bengal",
"country": "India",
"pincode": 700028,
"location_id": null,
"travelled": null,
"adharcard": "34567890",
"pancard": "ATD8994568",
"specialisation": "Vastushastri",
"services": [
"Artrology",
"Numerology"
],
"min_charge": "500",
"max_charge": "1000",
"online_charge": "700",
"qualification": "Test1",
"experience": "12 Years",
"language": "Bengali",
"active": "0",
"varify": "1",
"payment_mode": "{\"bank_name\":\"HDFC Bank\",\"bank_address\":\"Dum Dum Cant\",\"ifsc_code\":\"HDFC098765\",\"account_no\":\"987654654678\",\"account_holder\":\"Abit Roy\"}",
"created_at": "2020-08-31T19:03:56.000000Z",
"updated_at": "2020-09-16T12:40:54.000000Z"
},
"visits": [
{
"id": 70,
"pandit_activity_id": 22,
"pandit_id": 10,
"checkIn": "2020-09-03 02:00:00",
"checkOut": null,
"created_at": "2020-09-02T20:30:00.000000Z",
"updated_at": "2020-09-02T20:30:00.000000Z"
},
{
"id": 71,
"pandit_activity_id": 22,
"pandit_id": 10,
"checkIn": null,
"checkOut": "2020-09-03 02:00:15",
"created_at": "2020-09-02T20:30:15.000000Z",
"updated_at": "2020-09-02T20:30:15.000000Z"
}
]
}
Lead Model
import 'dart:convert';
import 'package:PandeetApp/models/client_need.dart';
import 'package:PandeetApp/models/pandit.dart';
import 'package:PandeetApp/models/visit.dart';
import 'package:PandeetApp/services/lead.dart';
class Lead extends LeadService {
int id;
int clientNeedId;
ClientNeed clientNeed;
String quoteDetails;
String quoteAmount;
int isCalled;
int isChecked;
int isAccept;
int isGoing;
String checkIn;
String checkOut;
int panditId;
Pandit pandit;
List<Visit> visits;
Lead({
this.id,
this.clientNeedId,
this.clientNeed,
this.quoteDetails,
this.quoteAmount,
this.isCalled,
this.isChecked,
this.isAccept,
this.isGoing,
this.checkIn,
this.checkOut,
this.panditId,
this.pandit,
this.visits,
});
Future<List<Lead>> fetchLeads() async {
var datas = await super.fetchDatas();
var dataList = json.decode(datas);
var leads = dataList.map((e) => Lead.fromJson(e)).toList();
return leads;
}
factory Lead.fromJson(Map<String, dynamic> json) {
List<Visit> visits = List<Visit>();
if (json['visits'] != null) {
json['visits'].forEach((v) {
visits.add(Visit.fromJson(v));
});
}
return Lead(
id: json['id'],
clientNeedId: json['client_need_id'],
clientNeed: json['clientNeed'] != null
? ClientNeed.fromJson(json['clientNeed'])
: ClientNeed(),
quoteDetails: json['quote_details'],
quoteAmount: json['quote_amount'],
isCalled: json['isCalled'],
isChecked: json['isChecked'],
isAccept: json['isAccept'],
isGoing: json['isGoing'],
checkIn: json['checkIn'],
checkOut: json['checkOut'],
panditId: json['pandit_id'],
pandit:
json['pandit'] != null ? Pandit.fromJson(json['pandit']) : Pandit(),
visits: visits,
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
if (this.clientNeed != null) {
data['clientNeed'] = this.clientNeed.toJson();
}
data['quote_details'] = this.quoteDetails;
data['quote_amount'] = this.quoteAmount;
data['isCalled'] = this.isCalled;
data['isChecked'] = this.isChecked;
data['isAccept'] = this.isAccept;
data['isGoing'] = this.isGoing;
data['checkIn'] = this.checkIn;
data['checkOut'] = this.checkOut;
if (this.pandit != null) {
data['pandit'] = this.pandit.toJson();
}
if (this.visits != null) {
data['visits'] = this.visits.map((v) => v.toJson()).toList();
}
return data;
}
}
Screen Part
FutureBuilder<List<Lead>>(
future: lead.fetchLeads(),
builder: (context, snapshot) {
if (snapshot.hasData) {
List leads = snapshot.data;
// print(leads.length); // Data Not Getting Here
if (leads.length > 0) {
return dataList(leads);
} else {
return Container(
padding: EdgeInsets.only(top: 200),
child: Text("You have no clients"),
);
}
} else if (snapshot.hasError) {
print(snapshot.error);
return Text("Server is Down now. Try again later");
}
return Container(
padding: EdgeInsets.only(top: 200),
child: CircularProgressIndicator(
backgroundColor: Colors.redAccent,
),
);
},
);
I think here have the problem. I was completed my project but this type of problem ruin my project. I could not understand where i am wrong for this problem. Exact line number could not found. Give just hint but where exactly problem not understandable. Please help me as soon as possible.
Don't cast the snapshot data as List instead use var. Try the print results before error and proceed further
FutureBuilder<List<Lead>>(
future: lead.fetchLeads(),
builder: (context, snapshot) {
if (snapshot.hasData) {
var leads = snapshot.data; // use var instead of List
// try this in your case it is received as String
print(leads.runtimeType.toString())
// if it is string convert to List.
var leadsJson = jsonDecode(leads)

Flutter how to add billing address with Stripe?

I am trying to learn how to (and best practices) to integrate Stripe into my mobile app.
I know from another post (Why there is no billing address in stripe Checkout) that Stripe has deprecated Billing Address Support however, I'd still want to be able to add that functionality into my app.
Currently the code I have is:
Future<void> createPaymentMethod(BuildContext context,
Map<String, String> billingAddress, String name, String phoneNumber) async {
StripePayment.setStripeAccount(null);
// Here to add the credit Card
PaymentMethod paymentMethod = PaymentMethod();
paymentMethod = await StripePayment.paymentRequestWithCardForm(
CardFormPaymentRequest(),
).then((PaymentMethod paymentMethod) {
paymentMethod.billingDetails = BillingDetails.fromJson({
'address': billingAddress,
'name': name,
'phone': phoneNumber,
});
return paymentMethod;
}).catchError((e) {
print('Error Card: ${e.toString()}');
});
paymentMethod != null
? processPaymentAsDirectCharge(paymentMethod,
context)
: AwesomeDialog(
context: context,
title: 'Uh oh! A wild error has appeared!',
desc:
'Seems like we cant process this card. Please double check your input or try a different card',
animType: AnimType.SCALE,
dialogType: DialogType.WARNING,
btnOkOnPress: () {})
.show();
}
Where I have a button that does:
onPressed: () {
createPaymentMethod(
context,
{
'city': cityController.text,
'line1': streetAddressController.text,
'postal_code': zipcodeController.text, // **postal_code does not show up for some reason**
'state': stateController.text
},
fullNameController.text,
'8007897890');
}
And What I got back from the paymentMethod in my console is:
paymentMethod: {
created: 1599242290.0,
id: pm_someIdHereThatGotReplacedByThis,
livemode: false,
type: card,
billingDetails: {name: John Doe,
phone: phoneNumber,
address: {city: Doggo Town, line1: 555 Puppy Street, state: CA}},
card: {addressLine1: null, addressLine2: null, brand: visa, country: US, expMonth: 4,
expYear: 2024, funding: credit, last4: 4242}}
However, in my Logs in Stripe it shows:
{
"id": "pm_someIdHereThatGotReplacedByThis",
"object": "payment_method",
"billing_details": {
"address": {
"city": null,
"country": "US",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": null,
"name": null,
"phone": null
},
"card": {
"brand": "visa",
"checks": {
"address_line1_check": null,
"address_postal_code_check": null,
"cvc_check": null
},
"country": "US",
"exp_month": 4,
"exp_year": 2024,
"funding": "credit",
"generated_from": null,
"last4": "4242",
"networks": {
"available": [
"visa"
],
"preferred": null
},
"three_d_secure_usage": {
"supported": true
},
"wallet": null
},
"created": 1599240880,
"customer": null,
"livemode": false,
"metadata": {
},
"type": "card"
}
my question is:
How do I setup my function so that the "checks" and "billing_details" fields will be filled with the information provided by the customer? Should I be adding something to the function
paymentMethod = await StripePayment.paymentRequestWithCardForm(
CardFormPaymentRequest()).then(...)
This is the field I am talking about:
"checks": {
"address_line1_check": null,
"address_postal_code_check": null,
"cvc_check": null
},
"billing_details": {
"address": {
"city": null,
"country": "US",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": null,
"name": null,
"phone": null
},
Thanks