Merhaba, wordpress arka uçlu çalışan bir flutter projem var. Woocommerce eklentisi ve shopier sanal pos eklentisi ile ödeme almayı planlıyorum. Web sitesinde kredi kartı ile alışveriş yapabiliyorum. Mobil uygulamada ise ödeme seçeneği otomatik olarak kapıda ödeme olarak gözüküyor. Kredi kartı ile ödeme seçeneğini kullanıcılara sunamıyorum. İlgili olduğunu düşündüğüm dart dosyasını sizinle paylaşıyorum. Nerede nasıl bir değişiklik yapmam lazım, yardımcı olabilir misiniz?

class PaymentModel {
String? connectionUrl;
String? description;
bool? enabled;
String? id;
String? methodDescription;
List<String>? methodSupports;
String? methodTitle;
bool? needsSetup;
//num? order;
Settings? settings;
String? settingsUrl;
var title;
// type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
PaymentModel({
this.connectionUrl,
this.description,
this.enabled,
this.id,
this.methodDescription,
this.methodSupports,
this.methodTitle,
this.needsSetup,
//this.order,
this.settings,
this.settingsUrl,
this.title,
});
factory PaymentModel.fromJson(Map<String, dynamic> json) {
return PaymentModel(
connectionUrl: json['connection_url'],
description: json['description'],
enabled: json['enabled'],
id: json['id'],
methodDescription: json['method_description'],
methodSupports: json['method_supports'] != null ? new List<String>.from(json['method_supports']) : null,
methodTitle: json['method_title'],
needsSetup: json['needs_setup'],
//order: json['order'],
//settings: json['settings'] != null ? Settings.fromJson(json['settings']) : null,
settingsUrl: json['settings_url'],
title: json['title'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['description'] = this.description;
data['enabled'] = this.enabled;
data['id'] = this.id;
data['method_description'] = this.methodDescription;
data['method_title'] = this.methodTitle;
data['needs_setup'] = this.needsSetup;
//data['order'] = this.order;
data['settings_url'] = this.settingsUrl;
data['title'] = this.title;
if (this.connectionUrl != null) {
data['connection_url'] = this.connectionUrl;
}
if (this.methodSupports != null) {
data['method_supports'] = this.methodSupports;
}
if (this.settings != null) {
data['settings'] = this.settings!.toJson();
}
return data;
}
}
class Settings {
EnableForMethods? enableForMethods;
EnableForVirtual? enableForVirtual;
Instructions? instructions;
Title? title;
Settings({this.enableForMethods, this.enableForVirtual, this.instructions, this.title});
factory Settings.fromJson(Map<String, dynamic> json) {
return Settings(
enableForMethods: json['enable_for_methods'] != null ? EnableForMethods.fromJson(json['enable_for_methods']) : null,
enableForVirtual: json['enable_for_virtual'] != null ? EnableForVirtual.fromJson(json['enable_for_virtual']) : null,
instructions: json['instructions'] != null ? Instructions.fromJson(json['instructions']) : null,
title: json['title'] != null ? Title.fromJson(json['title']) : null,
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.enableForMethods != null) {
data['enable_for_methods'] = this.enableForMethods!.toJson();
}
if (this.enableForVirtual != null) {
data['enable_for_virtual'] = this.enableForVirtual!.toJson();
}
if (this.instructions != null) {
data['instructions'] = this.instructions!.toJson();
}
if (this.title != null) {
data['title'] = this.title!.toJson();
}
return data;
}
}
class Instructions {
String? defaultValue;
String? description;
String? id;
String? label;
String? placeholder;
String? tip;
String? type;
String? value;
Instructions({this.defaultValue, this.description, this.id, this.label, this.placeholder, this.tip, this.type, this.value});
factory Instructions.fromJson(Map<String, dynamic> json) {
return Instructions(
defaultValue: json['default'],
description: json['description'],
id: json['id'],
label: json['label'],
placeholder: json['placeholder'],
tip: json['tip'],
type: json['type'],
value: json['value'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['default'] = this.defaultValue;
data['description'] = this.description;
data['id'] = this.id;
data['label'] = this.label;
data['placeholder'] = this.placeholder;
data['tip'] = this.tip;
data['type'] = this.type;
data['value'] = this.value;
return data;
}
}
class EnableForMethods {
String? defaultValue;
String? description;
String? id;
String? label;
Options? options;
String? placeholder;
String? tip;
String? type;
String? value;
EnableForMethods({this.defaultValue, this.description, this.id, this.label, this.options, this.placeholder, this.tip, this.type, this.value});
factory EnableForMethods.fromJson(Map<String, dynamic> json) {
return EnableForMethods(
defaultValue: json['default'],
description: json['description'],
id: json['id'],
label: json['label'],
options: json['options'] != null ? Options.fromJson(json['options']) : null,
placeholder: json['placeholder'],
tip: json['tip'],
type: json['type'],
value: json['value'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['default'] = this.defaultValue;
data['description'] = this.description;
data['id'] = this.id;
data['label'] = this.label;
data['placeholder'] = this.placeholder;
data['tip'] = this.tip;
data['type'] = this.type;
data['value'] = this.value;
if (this.options != null) {
data['options'] = this.options!.toJson();
}
return data;
}
}
class Options {
LocalPickup? pickup;
FlatRate? rate;
FreeShipping? shipping;
Options({this.pickup, this.rate, this.shipping});
factory Options.fromJson(Map<String, dynamic> json) {
return Options(
pickup: json['pickup'] != null ? LocalPickup.fromJson(json['pickup']) : null,
rate: json['rate'] != null ? FlatRate.fromJson(json['rate']) : null,
shipping: json['shipping'] != null ? FreeShipping.fromJson(json['shipping']) : null,
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.pickup != null) {
data['pickup'] = this.pickup!.toJson();
}
if (this.rate != null) {
data['rate'] = this.rate!.toJson();
}
if (this.shipping != null) {
data['shipping'] = this.shipping!.toJson();
}
return data;
}
}
class FlatRate {
String? flat_rate;
FlatRate({this.flat_rate});
factory FlatRate.fromJson(Map<String, dynamic> json) {
return FlatRate(
flat_rate: json['flat_rate'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['flat_rate'] = this.flat_rate;
return data;
}
}
class FreeShipping {
String? freeShipping;
FreeShipping({this.freeShipping});
factory FreeShipping.fromJson(Map<String, dynamic> json) {
return FreeShipping(
freeShipping: json['free_shipping'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['free_shipping'] = this.freeShipping;
return data;
}
}
class LocalPickup {
String? localPickup;
LocalPickup({this.localPickup});
factory LocalPickup.fromJson(Map<String, dynamic> json) {
return LocalPickup(
localPickup: json['local_pickup'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['local_pickup'] = this.localPickup;
return data;
}
}
class EnableForVirtual {
String? defaultValue;
String? description;
String? id;
String? label;
String? placeholder;
String? tip;
String? type;
String? value;
EnableForVirtual({this.defaultValue, this.description, this.id, this.label, this.placeholder, this.tip, this.type, this.value});
factory EnableForVirtual.fromJson(Map<String, dynamic> json) {
return EnableForVirtual(
defaultValue: json['default'],
description: json['description'],
id: json['id'],
label: json['label'],
placeholder: json['placeholder'],
tip: json['tip'],
type: json['type'],
value: json['value'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['default'] = this.defaultValue;
data['description'] = this.description;
data['id'] = this.id;
data['label'] = this.label;
data['placeholder'] = this.placeholder;
data['tip'] = this.tip;
data['type'] = this.type;
data['value'] = this.value;
return data;
}
}
class Title {
String? defaultValue;
String? description;
String? id;
String? label;
String? placeholder;
String? tip;
String? type;
String? value;
Title({this.defaultValue, this.description, this.id, this.label, this.placeholder, this.tip, this.type, this.value});
factory Title.fromJson(Map<String, dynamic> json) {
return Title(
defaultValue: json['default'],
description: json['description'],
id: json['id'],
label: json['label'],
placeholder: json['placeholder'],
tip: json['tip'],
type: json['type'],
value: json['value'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['default'] = this.defaultValue;
data['description'] = this.description;
data['id'] = this.id;
data['label'] = this.label;
data['placeholder'] = this.placeholder;
data['tip'] = this.tip;
data['type'] = this.type;
data['value'] = this.value;
return data;
}
}import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:nb_utils/nb_utils.dart';
import 'package:socialv/components/loading_widget.dart';
import 'package:socialv/main.dart';
import 'package:socialv/models/woo_commerce/billing_address_model.dart';
import 'package:socialv/models/woo_commerce/cart_item_model.dart';
import 'package:socialv/models/woo_commerce/cart_model.dart';
import 'package:socialv/models/woo_commerce/payment_model.dart';
import 'package:socialv/network/rest_apis.dart';
import 'package:socialv/screens/settings/screens/edit_shop_details_screen.dart';
import 'package:socialv/screens/shop/components/price_widget.dart';
import 'package:socialv/screens/shop/screens/order_detail_screen.dart';
import 'package:socialv/utils/app_constants.dart';
import 'package:socialv/utils/cached_network_image.dart';
class CheckoutScreen extends StatefulWidget {
final CartModel cartDetails;
CheckoutScreen({required this.cartDetails});
@override
State<CheckoutScreen> createState() => _CheckoutScreenState();
}
class _CheckoutScreenState extends State<CheckoutScreen> {
late CartModel cart;
bool isError = false;
bool isChange = false;
bool isPaymentGatewayLoading = true;
PaymentModel? selectedPaymentMethod;
List<PaymentModel> paymentGateways = [];
BillingAddressModel billingAddress = BillingAddressModel();
TextEditingController orderNotesController = TextEditingController();
@override
void initState() {
cart = widget.cartDetails;
billingAddress = widget.cartDetails.billingAddress!;
super.initState();
init();
}
Future<void> init() async {
isPaymentGatewayLoading = true;
setState(() {});
await getPaymentMethods().then((value) {
paymentGateways.addAll(value);
selectedPaymentMethod = value.firstWhere((element) => element.id == 'cod');
isPaymentGatewayLoading = false;
setState(() {});
}).catchError((e) {
isPaymentGatewayLoading = false;
toast(e.toString(), print: true);
setState(() {});
});
}
Future<void> getCart({String? orderBy}) async {
appStore.setLoading(true);
await getCartDetails().then((value) {
cart = value;
billingAddress = value.billingAddress!;
setState(() {});
appStore.setLoading(false);
}).catchError((e) {
isError = true;
appStore.setLoading(false);
toast(e.toString(), print: true);
});
}
Future<void> placeOrder() async {
ifNotTester(() async {
Map request = {
"payment_method": selectedPaymentMethod!.id,
"payment_method_title": selectedPaymentMethod!.title,
"set_paid": false,
'customer_id': appStore.loginUserId,
'status': "pending",
"billing": cart.billingAddress!.toJson(),
"shipping": cart.shippingAddress!.toJson(),
"line_items": cart.items!.map((e) {
return {"product_id": e.id, "quantity": e.quantity};
}).toList(),
"shipping_lines": [
{"method_id": "flat_rate", "method_title": "Flat Rate", "total": getPrice(cart.totals!.totalPrice.validate())}
]
};
appStore.setLoading(true);
await createOrder(request: request).then((value) async {
if (orderNotesController.text.isNotEmpty) {
Map noteRequest = {"note": orderNotesController.text.trim(), "customer_note": true};
await createOrderNotes(request: noteRequest, orderId: value.id.validate()).then((value) {}).catchError((e) {
log('Order Note Error: ${e.toString()}');
});
}
cart.items!.forEach((element) {
removeCartItem(productKey: element.key.validate()).then((value) {
log('removed');
}).catchError((e) {
//
});
});
cart.coupons!.forEach((coupon) {
removeCoupon(code: coupon.code.validate()).then((value) {
log('Coupon removed');
}).catchError((e) {
log('error remove coupon: ${e.toString()}');
});
});
appStore.setLoading(false);
finish(context);
finish(context);
OrderDetailScreen(orderDetails: value).launch(context);
}).catchError((e) {
appStore.setLoading(false);
toast(e.toString(), print: true);
});
});
}
@override
void setState(fn) {
if (mounted) super.setState(fn);
}
@override
void dispose() {
appStore.setLoading(false);
super.dispose();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
finish(context, isChange);
return Future.value(true);
},
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: context.iconColor),
onPressed: () {
finish(context, isChange);
},
),
titleSpacing: 0,
title: Text(language.checkout, style: boldTextStyle(size: 22)),
elevation: 0,
centerTitle: true,
),
body: Stack(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(language.products, style: boldTextStyle()),
16.height.visible(cart.items.validate().isNotEmpty),
if (cart.items.validate().isNotEmpty)
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: cart.items!.length,
itemBuilder: (ctx, index) {
CartItemModel cartItem = cart.items![index];
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cachedImage(
cartItem.images.validate().isNotEmpty ? cartItem.images!.first.src.validate() : '',
height: 50,
width: 50,
fit: BoxFit.cover,
).cornerRadiusWithClipRRect(4),
16.width,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(cartItem.name.validate(), style: primaryTextStyle()),
Text('${cartItem.quantity.validate()}*${getPrice(cartItem.prices!.currencySymbol.validate())}${getPrice(cartItem.prices!.price.validate())}',
style: secondaryTextStyle()),
],
).expand(),
PriceWidget(price: getPrice(cartItem.totals!.lineTotal.validate()).toString(), size: 16),
16.width,
Image.asset(ic_delete, color: Colors.red, height: 18, width: 18, fit: BoxFit.cover).onTap(() {
showConfirmDialogCustom(
context,
onAccept: (c) {
appStore.setLoading(true);
removeCartItem(productKey: cartItem.key.validate()).then((value) {
toast(language.itemRemovedSuccessfully);
getCart();
isChange = true;
}).catchError((e) {
appStore.setLoading(false);
toast(e.toString(), print: true);
});
},
dialogType: DialogType.CONFIRMATION,
title: language.removeFromCartConfirmation,
positiveText: language.remove,
);
}, splashColor: Colors.transparent, highlightColor: Colors.transparent).paddingSymmetric(vertical: 4),
],
).paddingSymmetric(vertical: 8);
},
)
else
Text(language.yourCartIsCurrentlyEmpty, style: secondaryTextStyle()),
16.height,
Container(
decoration: BoxDecoration(color: context.cardColor, borderRadius: radius(commonRadius)),
padding: EdgeInsets.only(left: 16, right: 8, bottom: 16, top: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('${language.total}: ', style: boldTextStyle()),
PriceWidget(price: getPrice(cart.totals!.totalPrice.validate())),
],
),
),
16.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(language.billingAddress, style: boldTextStyle()),
Image.asset(ic_edit, width: 18, height: 18, fit: BoxFit.cover, color: context.primaryColor).onTap(() {
EditShopDetailsScreen().launch(context).then((value) {
if (value ?? false) getCart();
});
}),
],
),
10.height,
Wrap(
children: [
Text('${billingAddress.company}, ', style: secondaryTextStyle()).visible(billingAddress.company.validate().isNotEmpty),
Text('${billingAddress.address_1}, ', style: secondaryTextStyle()).visible(billingAddress.address_1.validate().isNotEmpty),
Text('${billingAddress.address_2}, ', style: secondaryTextStyle()).visible(billingAddress.address_2.validate().isNotEmpty),
Text('${billingAddress.city}, ', style: secondaryTextStyle()).visible(billingAddress.city.validate().isNotEmpty),
Text('${billingAddress.state}, ', style: secondaryTextStyle()).visible(billingAddress.state.validate().isNotEmpty),
Text('${billingAddress.country}', style: secondaryTextStyle()).visible(billingAddress.country.validate().isNotEmpty),
],
),
Text('${language.postCode}: ${billingAddress.postcode}', style: secondaryTextStyle()).visible(billingAddress.postcode.validate().isNotEmpty),
Text('${language.phone}: ${billingAddress.phone}', style: secondaryTextStyle()).visible(billingAddress.phone.validate().isNotEmpty),
Text('${language.email}: ${billingAddress.email}', style: secondaryTextStyle()).visible(billingAddress.email.validate().isNotEmpty),
16.height,
Text(language.selectPaymentMethod, style: boldTextStyle()),
!isPaymentGatewayLoading
? paymentGateways.isNotEmpty
? Container(
decoration: BoxDecoration(color: context.cardColor, borderRadius: radius(defaultAppButtonRadius)),
margin: EdgeInsets.symmetric(vertical: 16),
padding: EdgeInsets.all(16),
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: paymentGateways.length,
itemBuilder: (ctx, index) {
if (paymentGateways[index].id.validate() == 'Cash on delivery') {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(selectedPaymentMethod == paymentGateways[index] ? Icons.radio_button_checked : Icons.radio_button_off, color: context.primaryColor, size: 20),
8.width,
Text(paymentGateways[index].title.validate(), style: primaryTextStyle()),
],
),
Container(
child: Text(paymentGateways[index].description.validate(), style: secondaryTextStyle(size: 12)),
decoration: BoxDecoration(color: context.scaffoldBackgroundColor, borderRadius: radius(commonRadius)),
padding: EdgeInsets.all(8),
margin: EdgeInsets.only(top: 4),
).visible(selectedPaymentMethod == paymentGateways[index])
],
).onTap(() {
selectedPaymentMethod = paymentGateways[index];
setState(() {});
}, splashColor: Colors.transparent, highlightColor: Colors.transparent);
} else {
return Offstage();
}
},
),
)
: Text(language.paymentGatewaysNotFound, style: secondaryTextStyle())
: ThreeBounceLoadingWidget(),
16.height,
Text(language.placeOrderText, style: secondaryTextStyle()),
16.height,
RichText(
text: TextSpan(
text: '${language.addOrderNotes} ',
style: boldTextStyle(),
children: <TextSpan>[
TextSpan(text: '(${language.optional})', style: secondaryTextStyle(size: 12)),
],
),
),
10.height,
Text(language.notesAboutYourOrder, style: secondaryTextStyle()),
16.height,
AppTextField(
controller: orderNotesController,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.done,
textFieldType: TextFieldType.MULTILINE,
textStyle: boldTextStyle(),
minLines: 3,
maxLines: 3,
decoration: inputDecorationFilled(context, fillColor: context.cardColor, label: 'Notes'),
validator: (value) {
if (value == null || value.isEmpty) {
return language.pleaseEnterDescription;
}
return null;
},
),
16.height,
appButton(
context: context,
text: language.placeOrder,
onTap: () async {
if (cart.items.validate().isNotEmpty) {
if (cart.billingAddress!.address_1.validate().isNotEmpty || cart.billingAddress!.address_2.validate().isNotEmpty || cart.billingAddress!.city.validate().isNotEmpty) {
placeOrder();
} else {
toast(language.pleaseEnterValidBilling);
}
} else {
toast(language.yourCartIsCurrentlyEmpty);
}
},
),
50.height,
],
).paddingSymmetric(horizontal: 16),
),
Observer(builder: (_) => LoadingWidget().center().visible(appStore.isLoading)),
],
),
),
);
}
}
// .catchError((e) {
// isPaymentGatewayLoading = false;
// toast(e.toString(), print: true);
// setState(() {});
// });