RazorPay checkout added, Option to use shipping address, Config update, Pubspec.yaml change, Option to use different billing or shipping address, Bug fixes

This commit is contained in:
WooSignal 2020-05-16 20:30:34 +01:00
parent c399e882f8
commit 97c9499f3e
15 changed files with 713 additions and 165 deletions

View File

@ -1,3 +1,12 @@
## [2.0.5] - 2020-05-16
* RazorPay checkout added
* Option to use shipping address
* Config update
* Pubspec.yaml change
* Option to use different billing or shipping address
* Bug fixes
## [2.0.4] - 2020-05-13
* Added Flexible widget for checkout details

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -272,6 +272,8 @@
"${BUILT_PRODUCTS_DIR}/flutter_web_browser/flutter_web_browser.framework",
"${BUILT_PRODUCTS_DIR}/package_info/package_info.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
"${PODS_ROOT}/razorpay-pod/Pod/Razorpay.framework",
"${BUILT_PRODUCTS_DIR}/razorpay_flutter/razorpay_flutter.framework",
"${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
@ -287,6 +289,8 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_web_browser.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Razorpay.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/razorpay_flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",

View File

@ -127,6 +127,7 @@
"Done": "Done",
"Billing Details": "Billing Details",
"Shipping Details": "Shipping Details",
"Shipping Address": "Shipping Address",
"State": "State",
"Country": "Country",
"UPDATE DETAILS": "UPDATE DETAILS",
@ -145,5 +146,9 @@
"Welcome back": "Welcome back",
"Quantity": "Quantity",
"Select a state": "Select a state",
"Select state": "Select state"
"Select state": "Select state",
"Ship to a different address?": "Ship to a different address?",
"USE DETAILS": "USE DETAILS",
"Not supported, try a card payment": "Not supported, try a card payment",
"Invalid shipping address, please check your shipping details": "Invalid shipping address, please check your shipping details"
}

View File

@ -11,6 +11,7 @@
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/payment_type.dart';
import 'package:label_storemax/providers/cash_on_delivery.dart';
import 'package:label_storemax/providers/razor_pay.dart';
import 'package:label_storemax/providers/stripe_pay.dart';
// Payment methods available for uses in the app
@ -36,15 +37,25 @@ List<PaymentType> arrPaymentMethods = [
),
),
addPayment(
PaymentType(
id: 3,
name: "RazorPay",
desc: "Debit or Credit Card",
assetImage: "razorpay.png",
pay: razorPay,
),
),
// e.g. add more here
// addPayment(
// PaymentType(
// id: 3,
// id: 4,
// name: "MyNewPaymentMethod",
// desc: "Debit or Credit Card",
// assetImage: "add icon image to assets/images/myimage.png",
// pay: stripePay
// pay: myCustomPaymentFunction
// ),
// ),
];

View File

@ -66,6 +66,9 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
billing.postcode = billingDetails.billingAddress.postalCode;
billing.country = billingDetails.billingAddress.country;
billing.email = billingDetails.billingAddress.emailAddress;
if (billingDetails.billingAddress.country == "United States") {
billing.state = billingDetails.billingAddress.state;
}
orderWC.billing = billing;
@ -75,6 +78,9 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
shipping.address1 = billingDetails.shippingAddress.addressLine;
shipping.city = billingDetails.shippingAddress.city;
shipping.postcode = billingDetails.shippingAddress.postalCode;
if (billingDetails.shippingAddress.country == "United States") {
shipping.state = billingDetails.shippingAddress.state;
}
shipping.country = billingDetails.shippingAddress.country;
orderWC.shipping = shipping;

View File

@ -16,7 +16,7 @@ import 'dart:ui';
Developer Notes
SUPPORT EMAIL - support@woosignal.com
VERSION - 2.0.4
VERSION - 2.0.5
https://woosignal.com
*/
@ -24,7 +24,8 @@ import 'dart:ui';
const app_name = "MyApp";
const app_key = "Your app key from WooSignal";
const app_key =
"app_b2538b4325a4a6b0f3b919f4c91cea8087ba80977f4a7c1feda669127aca";
// Your App key from WooSignal
// link: https://woosignal.com/dashboard/apps
@ -47,7 +48,7 @@ const app_locales_supported = [
/*<! ------ PAYMENT GATEWAYS ------!>*/
// Available: "Stripe", "CashOnDelivery",
// Available: "Stripe", "CashOnDelivery", "RazorPay"
// Add the method to the array below e.g. ["Stripe", "CashOnDelivery"]
const app_payment_methods = ["Stripe"];
@ -78,6 +79,11 @@ const app_forgot_password_url =
"https://mysite.com/my-account/lost-password"; // change to your forgot password url
const app_wp_api_path = "/wp-json"; // By default "/wp-json" should work
/*<! ------ Razor Pay (OPTIONAL) ------!>*/
// https://razorpay.com/
const app_razor_id = "Your Razor ID from RazorPay";
/*<! ------ DEBUGGER ENABLED ------!>*/
const app_debug = true;

View File

@ -21,7 +21,10 @@ import 'package:woosignal/models/response/tax_rate.dart';
import '../helpers/tools.dart';
class CheckoutSession {
String sfKeyCheckout = "CS_BILLING_DETAILS";
String sfKeyBillingCheckout = "CS_BILLING_DETAILS";
String sfKeyShippingCheckout = "CS_SHIPPING_DETAILS";
bool shipToDifferentAddress = false;
CheckoutSession._privateConstructor();
static final CheckoutSession getInstance =
CheckoutSession._privateConstructor();
@ -35,19 +38,25 @@ class CheckoutSession {
shippingType = null;
}
void clear() {
billingDetails = null;
shippingType = null;
paymentType = null;
}
void saveBillingAddress() {
SharedPref sharedPref = SharedPref();
CustomerAddress customerAddress =
CheckoutSession.getInstance.billingDetails.billingAddress;
String billingAddress = jsonEncode(customerAddress.toJson());
sharedPref.save(sfKeyCheckout, billingAddress);
sharedPref.save(sfKeyBillingCheckout, billingAddress);
}
Future<CustomerAddress> getBillingAddress() async {
SharedPref sharedPref = SharedPref();
String strCheckoutDetails = await sharedPref.read(sfKeyCheckout);
String strCheckoutDetails = await sharedPref.read(sfKeyBillingCheckout);
if (strCheckoutDetails != null && strCheckoutDetails != "") {
return CustomerAddress.fromJson(jsonDecode(strCheckoutDetails));
@ -57,7 +66,30 @@ class CheckoutSession {
void clearBillingAddress() {
SharedPref sharedPref = SharedPref();
sharedPref.remove(sfKeyCheckout);
sharedPref.remove(sfKeyBillingCheckout);
}
void saveShippingAddress() {
SharedPref sharedPref = SharedPref();
CustomerAddress customerAddress =
CheckoutSession.getInstance.billingDetails.shippingAddress;
String shippingAddress = jsonEncode(customerAddress.toJson());
sharedPref.save(sfKeyShippingCheckout, shippingAddress);
}
Future<CustomerAddress> getShippingAddress() async {
SharedPref sharedPref = SharedPref();
String strCheckoutDetails = await sharedPref.read(sfKeyShippingCheckout);
if (strCheckoutDetails != null && strCheckoutDetails != "") {
return CustomerAddress.fromJson(jsonDecode(strCheckoutDetails));
}
return null;
}
void clearShippingAddress() {
SharedPref sharedPref = SharedPref();
sharedPref.remove(sfKeyShippingCheckout);
}
Future<String> total({bool withFormat, TaxRate taxRate}) async {

View File

@ -291,14 +291,14 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
.getTotal(withFormatting: true)),
(_taxRate != null
? wsCheckoutTaxAmountWidgetFB(taxRate: _taxRate)
: Container()),
: null),
wsCheckoutTotalWidgetFB(
title: trans(context, "Total"), taxRate: _taxRate),
Divider(
color: Colors.black12,
thickness: 1,
),
],
].where((e) => e != null).toList(),
),
wsPrimaryButton(
context,

View File

@ -28,161 +28,44 @@ class CheckoutDetailsPage extends StatefulWidget {
class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
_CheckoutDetailsPageState();
bool _valDifferentShippingAddress = false;
int activeTabIndex = 0;
// BILLING TEXT CONTROLLERS
TextEditingController _txtBillingFirstName;
TextEditingController _txtBillingLastName;
TextEditingController _txtBillingAddressLine;
TextEditingController _txtBillingCity;
TextEditingController _txtBillingPostalCode;
TextEditingController _txtBillingEmailAddress;
TextEditingController _txtShippingFirstName;
TextEditingController _txtShippingLastName;
TextEditingController _txtShippingAddressLine;
TextEditingController _txtShippingCity;
TextEditingController _txtShippingPostalCode;
TextEditingController _txtShippingEmailAddress;
String _strBillingCountry;
String _strBillingState;
String _strShippingCountry;
String _strShippingState;
var valRememberDetails = true;
Widget activeTab;
@override
void initState() {
super.initState();
_txtShippingFirstName = TextEditingController();
_txtShippingLastName = TextEditingController();
_txtShippingAddressLine = TextEditingController();
_txtShippingCity = TextEditingController();
_txtShippingPostalCode = TextEditingController();
_txtShippingEmailAddress = TextEditingController();
if (CheckoutSession.getInstance.billingDetails.billingAddress == null) {
CheckoutSession.getInstance.billingDetails.initSession();
CheckoutSession.getInstance.billingDetails.shippingAddress.initAddress();
CheckoutSession.getInstance.billingDetails.billingAddress.initAddress();
}
BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails;
_txtShippingFirstName.text = billingDetails.billingAddress.firstName;
_txtShippingLastName.text = billingDetails.billingAddress.lastName;
_txtShippingAddressLine.text = billingDetails.billingAddress.addressLine;
_txtShippingCity.text = billingDetails.billingAddress.city;
_txtShippingPostalCode.text = billingDetails.billingAddress.postalCode;
_txtShippingEmailAddress.text = billingDetails.billingAddress.emailAddress;
_strBillingCountry = billingDetails.billingAddress.country;
_strBillingState = billingDetails.billingAddress.state;
valRememberDetails = billingDetails.rememberDetails ?? true;
_sfCustomerAddress();
}
_sfCustomerAddress() async {
CustomerAddress sfCustomerAddress =
await CheckoutSession.getInstance.getBillingAddress();
if (sfCustomerAddress != null) {
CustomerAddress customerAddress = sfCustomerAddress;
_txtShippingFirstName.text = customerAddress.firstName;
_txtShippingLastName.text = customerAddress.lastName;
_txtShippingAddressLine.text = customerAddress.addressLine;
_txtShippingCity.text = customerAddress.city;
_txtShippingPostalCode.text = customerAddress.postalCode;
_txtShippingEmailAddress.text = customerAddress.emailAddress;
_strBillingState = customerAddress.state;
_strBillingCountry = customerAddress.country;
}
}
_showSelectCountryModal() {
wsModalBottom(
context,
title: trans(context, "Select a country"),
bodyWidget: ListView.separated(
itemCount: appCountryOptions.length,
itemBuilder: (BuildContext context, int index) {
Map<String, String> strName = appCountryOptions[index];
return InkWell(
child: Container(
child: Text(strName["name"],
style: Theme.of(context).primaryTextTheme.bodyText1),
padding: EdgeInsets.only(top: 25, bottom: 25),
),
splashColor: Colors.grey,
highlightColor: Colors.black12,
onTap: () => setState(() {
_strBillingCountry = strName["name"];
Navigator.of(context).pop();
if (strName["code"] == "US") {
_showSelectStateModal();
} else {
_strBillingState = "";
}
}),
);
},
separatorBuilder: (cxt, i) => Divider(
height: 0,
color: Colors.black12,
),
),
);
}
_showSelectStateModal() {
wsModalBottom(
context,
title: trans(context, "Select a state"),
bodyWidget: ListView.separated(
itemCount: appStateOptions.length,
itemBuilder: (BuildContext context, int index) {
Map<String, String> strName = appStateOptions[index];
return InkWell(
child: Container(
child: Text(
strName["name"],
style: Theme.of(context).primaryTextTheme.bodyText1,
),
padding: EdgeInsets.only(top: 25, bottom: 25),
),
splashColor: Colors.grey,
highlightColor: Colors.black12,
onTap: () => setState(() {
_strBillingState = strName["name"];
Navigator.of(context).pop();
}),
);
},
separatorBuilder: (cxt, i) => Divider(
height: 0,
color: Colors.black12,
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text(
trans(context, "Billing & Shipping Details"),
style: Theme.of(context).primaryTextTheme.headline6,
),
centerTitle: true,
),
body: SafeArea(
minimum: safeAreaDefault(),
child: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
child: LayoutBuilder(
builder: (context, constraints) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
child: Container(
margin: EdgeInsets.only(top: 10),
Widget tabShippingDetails() {
return Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
_valDifferentShippingAddress
? Divider(
height: 0,
)
: null,
Flexible(
child: Row(
children: <Widget>[
@ -245,6 +128,124 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
],
),
),
Flexible(
child: Row(
children: <Widget>[
(_strShippingCountry == "United States"
? Flexible(
child: Padding(
child: wsSecondaryButton(
context,
title: (_strShippingState != null &&
_strShippingState.isNotEmpty
? trans(context, "Selected") +
"\n" +
_strShippingState
: trans(context, "Select state")),
action: () => _showSelectStateModal("shipping"),
),
padding: EdgeInsets.all(8),
),
)
: null),
Flexible(
child: Padding(
child: wsSecondaryButton(
context,
title: (_strShippingCountry != null &&
_strShippingCountry.isNotEmpty
? trans(context, "Selected") +
"\n" +
_strShippingCountry
: trans(context, "Select country")),
action: () => _showSelectCountryModal("shipping"),
),
padding: EdgeInsets.all(8),
),
),
].where((element) => element != null).toList(),
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
),
),
].where((e) => e != null).toList(),
),
);
}
Widget tabBillingDetails() {
return Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
_valDifferentShippingAddress
? Divider(
height: 0,
)
: null,
Flexible(
child: Row(
children: <Widget>[
Flexible(
child: wsTextEditingRow(
context,
heading: trans(context, "First Name"),
controller: _txtBillingFirstName,
shouldAutoFocus: true,
),
),
Flexible(
child: wsTextEditingRow(
context,
heading: trans(context, "Last Name"),
controller: _txtBillingLastName,
),
),
],
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
),
),
Flexible(
child: Row(
children: <Widget>[
Flexible(
child: wsTextEditingRow(
context,
heading: trans(context, "Address Line"),
controller: _txtBillingAddressLine,
),
),
Flexible(
child: wsTextEditingRow(
context,
heading: trans(context, "City"),
controller: _txtBillingCity,
),
),
],
),
),
Flexible(
child: Row(
children: <Widget>[
Flexible(
child: wsTextEditingRow(
context,
heading: trans(context, "Postal code"),
controller: _txtBillingPostalCode,
),
),
Flexible(
child: wsTextEditingRow(context,
heading: trans(context, "Email address"),
keyboardType: TextInputType.emailAddress,
controller: _txtBillingEmailAddress),
),
],
),
),
Flexible(
child: Row(
children: <Widget>[
@ -259,7 +260,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
"\n" +
_strBillingState
: trans(context, "Select state")),
action: _showSelectStateModal,
action: () => _showSelectStateModal("billing"),
),
padding: EdgeInsets.all(8),
),
@ -275,17 +276,297 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
"\n" +
_strBillingCountry
: trans(context, "Select country")),
action: _showSelectCountryModal,
action: () => _showSelectCountryModal("billing"),
),
padding: EdgeInsets.all(8),
),
)
),
].where((element) => element != null).toList(),
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
),
),
].where((e) => e != null).toList(),
),
);
}
@override
void initState() {
super.initState();
// SHIPPING
_txtShippingFirstName = TextEditingController();
_txtShippingLastName = TextEditingController();
_txtShippingAddressLine = TextEditingController();
_txtShippingCity = TextEditingController();
_txtShippingPostalCode = TextEditingController();
_txtShippingEmailAddress = TextEditingController();
// BILLING
_txtBillingFirstName = TextEditingController();
_txtBillingLastName = TextEditingController();
_txtBillingAddressLine = TextEditingController();
_txtBillingCity = TextEditingController();
_txtBillingPostalCode = TextEditingController();
_txtBillingEmailAddress = TextEditingController();
if (CheckoutSession.getInstance.billingDetails.billingAddress == null) {
CheckoutSession.getInstance.billingDetails.initSession();
CheckoutSession.getInstance.billingDetails.shippingAddress.initAddress();
CheckoutSession.getInstance.billingDetails.billingAddress.initAddress();
}
BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails;
_txtBillingFirstName.text = billingDetails.billingAddress.firstName;
_txtBillingLastName.text = billingDetails.billingAddress.lastName;
_txtBillingAddressLine.text = billingDetails.billingAddress.addressLine;
_txtBillingCity.text = billingDetails.billingAddress.city;
_txtBillingPostalCode.text = billingDetails.billingAddress.postalCode;
_txtBillingEmailAddress.text = billingDetails.billingAddress.emailAddress;
_strBillingCountry = billingDetails.billingAddress.country;
_strBillingState = billingDetails.billingAddress.state;
_txtShippingFirstName.text = billingDetails.shippingAddress.firstName;
_txtShippingLastName.text = billingDetails.shippingAddress.lastName;
_txtShippingAddressLine.text = billingDetails.shippingAddress.addressLine;
_txtShippingCity.text = billingDetails.shippingAddress.city;
_txtShippingPostalCode.text = billingDetails.shippingAddress.postalCode;
_txtShippingEmailAddress.text = billingDetails.shippingAddress.emailAddress;
_strShippingCountry = billingDetails.shippingAddress.country;
_strShippingState = billingDetails.shippingAddress.state;
_valDifferentShippingAddress =
CheckoutSession.getInstance.shipToDifferentAddress;
valRememberDetails = billingDetails.rememberDetails ?? true;
_sfCustomerAddress();
}
_sfCustomerAddress() async {
CustomerAddress sfCustomerBillingAddress =
await CheckoutSession.getInstance.getBillingAddress();
if (sfCustomerBillingAddress != null) {
CustomerAddress customerAddress = sfCustomerBillingAddress;
_txtBillingFirstName.text = customerAddress.firstName;
_txtBillingLastName.text = customerAddress.lastName;
_txtBillingAddressLine.text = customerAddress.addressLine;
_txtBillingCity.text = customerAddress.city;
_txtBillingPostalCode.text = customerAddress.postalCode;
_txtBillingEmailAddress.text = customerAddress.emailAddress;
_strBillingState = customerAddress.state;
_strBillingCountry = customerAddress.country;
}
CustomerAddress sfCustomerShippingAddress =
await CheckoutSession.getInstance.getShippingAddress();
if (sfCustomerShippingAddress != null) {
CustomerAddress customerAddress = sfCustomerShippingAddress;
_txtShippingFirstName.text = customerAddress.firstName;
_txtShippingLastName.text = customerAddress.lastName;
_txtShippingAddressLine.text = customerAddress.addressLine;
_txtShippingCity.text = customerAddress.city;
_txtShippingPostalCode.text = customerAddress.postalCode;
_txtShippingEmailAddress.text = customerAddress.emailAddress;
_strShippingCountry = customerAddress.country;
_strShippingState = customerAddress.state;
}
}
_showSelectCountryModal(String type) {
wsModalBottom(
context,
title: trans(context, "Select a country"),
bodyWidget: ListView.separated(
itemCount: appCountryOptions.length,
itemBuilder: (BuildContext context, int index) {
Map<String, String> strName = appCountryOptions[index];
return InkWell(
child: Container(
child: Text(strName["name"],
style: Theme.of(context).primaryTextTheme.bodyText1),
padding: EdgeInsets.only(top: 25, bottom: 25),
),
splashColor: Colors.grey,
highlightColor: Colors.black12,
onTap: () => setState(() {
if (type == "shipping") {
_strShippingCountry = strName["name"];
activeTab = tabShippingDetails();
Navigator.of(context).pop();
if (strName["code"] == "US") {
_showSelectStateModal(type);
} else {
_strShippingState = "";
}
} else if (type == "billing") {
_strBillingCountry = strName["name"];
Navigator.of(context).pop();
activeTab = tabBillingDetails();
if (strName["code"] == "US") {
_showSelectStateModal(type);
} else {
_strBillingState = "";
}
}
}),
);
},
separatorBuilder: (cxt, i) => Divider(
height: 0,
color: Colors.black12,
),
),
);
}
_showSelectStateModal(String type) {
wsModalBottom(
context,
title: trans(context, "Select a state"),
bodyWidget: ListView.separated(
itemCount: appStateOptions.length,
itemBuilder: (BuildContext context, int index) {
Map<String, String> strName = appStateOptions[index];
return InkWell(
child: Container(
child: Text(
strName["name"],
style: Theme.of(context).primaryTextTheme.bodyText1,
),
padding: EdgeInsets.only(top: 25, bottom: 25),
),
splashColor: Colors.grey,
highlightColor: Colors.black12,
onTap: () => setState(() {
if (type == "shipping") {
_strShippingState = strName["name"];
Navigator.of(context).pop();
activeTab = tabShippingDetails();
} else if (type == "billing") {
_strBillingState = strName["name"];
Navigator.of(context).pop();
activeTab = tabBillingDetails();
}
}),
);
},
separatorBuilder: (cxt, i) => Divider(
height: 0,
color: Colors.black12,
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text(
trans(context, "Billing & Shipping Details"),
style: Theme.of(context).primaryTextTheme.headline6,
),
centerTitle: true,
),
body: SafeArea(
minimum: safeAreaDefault(),
child: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
child: LayoutBuilder(
builder: (context, constraints) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
child: Container(
margin: EdgeInsets.only(top: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
_valDifferentShippingAddress
? Padding(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Flexible(
child: InkWell(
child: Container(
width: double.infinity,
child: Text(
trans(context, "Billing Details"),
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(
color: activeTabIndex == 0
? Colors.white
: Colors.black),
textAlign: TextAlign.center,
),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(4),
color: activeTabIndex == 0
? Colors.black
: Colors.white,
),
padding: EdgeInsets.symmetric(
horizontal: 4, vertical: 4),
),
onTap: () {
setState(() {
activeTabIndex = 0;
activeTab = tabBillingDetails();
});
},
),
),
Flexible(
child: InkWell(
child: Container(
width: double.infinity,
child: Text(
trans(context, "Shipping Address"),
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(
color: activeTabIndex == 1
? Colors.white
: Colors.black),
textAlign: TextAlign.center,
),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(4),
color: activeTabIndex == 1
? Colors.black
: Colors.white,
),
padding: EdgeInsets.symmetric(
horizontal: 4, vertical: 2),
),
onTap: () {
setState(() {
activeTabIndex = 1;
activeTab = tabShippingDetails();
});
},
),
)
],
].where((e) => e != null).toList(),
),
padding: EdgeInsets.symmetric(vertical: 8),
)
: null,
activeTab ?? tabBillingDetails(),
].where((e) => e != null).toList(),
),
decoration: BoxDecoration(
color: Colors.white,
@ -294,13 +575,28 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
),
padding: EdgeInsets.all(8),
),
height: (constraints.maxHeight - constraints.minHeight) * 0.6,
height:
(constraints.maxHeight - constraints.minHeight) * 0.62,
),
Column(
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
trans(context, "Ship to a different address?"),
style: Theme.of(context).primaryTextTheme.bodyText2,
),
Checkbox(
value: _valDifferentShippingAddress,
onChanged: _onChangeShipping,
)
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
trans(context, "Remember my details"),
@ -317,37 +613,8 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
],
),
wsPrimaryButton(context,
title: trans(context, "USE SHIPPING ADDRESS"),
action: () {
CustomerAddress customerAddress = new CustomerAddress();
customerAddress.firstName = _txtShippingFirstName.text;
customerAddress.lastName = _txtShippingLastName.text;
customerAddress.addressLine =
_txtShippingAddressLine.text;
customerAddress.city = _txtShippingCity.text;
customerAddress.postalCode = _txtShippingPostalCode.text;
customerAddress.state = _strBillingState;
customerAddress.country = _strBillingCountry;
customerAddress.emailAddress =
_txtShippingEmailAddress.text;
CheckoutSession.getInstance.billingDetails
.shippingAddress = customerAddress;
CheckoutSession.getInstance.billingDetails
.billingAddress = customerAddress;
CheckoutSession.getInstance.billingDetails
.rememberDetails = valRememberDetails;
if (valRememberDetails == true) {
CheckoutSession.getInstance.saveBillingAddress();
} else {
CheckoutSession.getInstance.clearBillingAddress();
}
CheckoutSession.getInstance.shippingType = null;
Navigator.pop(context);
}),
title: trans(context, "USE DETAILS"),
action: () => _useDetailsTapped()),
],
),
],
@ -357,4 +624,98 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
),
);
}
_useDetailsTapped() {
CustomerAddress customerBillingAddress = new CustomerAddress();
customerBillingAddress.firstName = _txtBillingFirstName.text;
customerBillingAddress.lastName = _txtBillingLastName.text;
customerBillingAddress.addressLine = _txtBillingAddressLine.text;
customerBillingAddress.city = _txtBillingCity.text;
customerBillingAddress.postalCode = _txtBillingPostalCode.text;
customerBillingAddress.state = _strBillingState;
customerBillingAddress.country = _strBillingCountry;
customerBillingAddress.emailAddress = _txtBillingEmailAddress.text;
if (!_valDifferentShippingAddress) {
CheckoutSession.getInstance.billingDetails.shippingAddress =
customerBillingAddress;
CheckoutSession.getInstance.billingDetails.billingAddress =
customerBillingAddress;
if (valRememberDetails == true) {
CheckoutSession.getInstance.saveBillingAddress();
}
} else {
CustomerAddress customerShippingAddress = new CustomerAddress();
customerShippingAddress.firstName = _txtShippingFirstName.text;
customerShippingAddress.lastName = _txtShippingLastName.text;
customerShippingAddress.addressLine = _txtShippingAddressLine.text;
customerShippingAddress.city = _txtShippingCity.text;
customerShippingAddress.postalCode = _txtShippingPostalCode.text;
customerShippingAddress.state = _strShippingState;
customerShippingAddress.country = _strShippingCountry;
customerShippingAddress.emailAddress = _txtShippingEmailAddress.text;
if (customerShippingAddress.hasMissingFields()) {
showEdgeAlertWith(context,
title: trans(context, "Oops"),
desc: trans(
context,
trans(context,
"Invalid shipping address, please check your shipping details"),
),
style: EdgeAlertStyle.WARNING);
return;
}
CheckoutSession.getInstance.billingDetails.billingAddress =
customerBillingAddress;
CheckoutSession.getInstance.billingDetails.shippingAddress =
customerShippingAddress;
if (valRememberDetails == true) {
CheckoutSession.getInstance.saveBillingAddress();
CheckoutSession.getInstance.saveShippingAddress();
}
}
CheckoutSession.getInstance.billingDetails.rememberDetails =
valRememberDetails;
if (valRememberDetails != true) {
CheckoutSession.getInstance.clearBillingAddress();
CheckoutSession.getInstance.clearShippingAddress();
}
CheckoutSession.getInstance.shipToDifferentAddress =
_valDifferentShippingAddress;
CheckoutSession.getInstance.shippingType = null;
Navigator.pop(context);
}
_onChangeShipping(bool value) async {
_valDifferentShippingAddress = value;
activeTabIndex = 1;
if (value == true) {
activeTab = tabShippingDetails();
} else {
activeTab = tabBillingDetails();
}
CustomerAddress sfCustomerShippingAddress =
await CheckoutSession.getInstance.getShippingAddress();
if (sfCustomerShippingAddress == null) {
_txtShippingFirstName.text = "";
_txtShippingLastName.text = "";
_txtShippingAddressLine.text = "";
_txtShippingCity.text = "";
_txtShippingPostalCode.text = "";
_txtShippingEmailAddress.text = "";
_strShippingState = "";
_strShippingCountry = "";
}
setState(() {});
}
}

View File

@ -15,6 +15,7 @@ import 'package:flutter/widgets.dart';
import 'package:label_storemax/helpers/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/pages/checkout_confirmation.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';
@ -29,6 +30,7 @@ cashOnDeliveryPay(context,
if (order != null) {
Cart.getInstance.clear();
CheckoutSession.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(

View File

@ -0,0 +1,94 @@
//
// LabelCore
// Label StoreMAX
//
// Created by Anthony Gordon.
// 2020, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
import 'package:flutter/widgets.dart';
import 'package:label_storemax/helpers/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/pages/checkout_confirmation.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart';
import 'package:woosignal/models/response/tax_rate.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';
razorPay(context,
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
Razorpay _razorpay = Razorpay();
_razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS,
(PaymentSuccessResponse response) async {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
Order order = await appWooSignal((api) => api.createOrder(orderWC));
if (order != null) {
Cart.getInstance.clear();
CheckoutSession.getInstance.clear();
_razorpay.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(context,
title: trans(context, "Error"),
desc: trans(
context,
trans(context, "Something went wrong, please contact our store"),
),
style: EdgeAlertStyle.WARNING);
_razorpay.clear();
state.reloadState(showLoader: false);
}
});
_razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, (PaymentFailureResponse response) {
showEdgeAlertWith(context,
title: trans(context, "Error"),
desc: response.message,
style: EdgeAlertStyle.WARNING);
_razorpay.clear();
state.reloadState(showLoader: false);
});
_razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET,
(ExternalWalletResponse response) {
showEdgeAlertWith(context,
title: trans(context, "Error"),
desc: trans(context, "Not supported, try a card payment"),
style: EdgeAlertStyle.WARNING);
_razorpay.clear();
state.reloadState(showLoader: false);
});
// CHECKOUT HELPER
await checkout(taxRate, (total, billingDetails, cart) async {
var options = {
'key': app_razor_id,
'amount': (parseWcPrice(total) * 100).toInt(),
'name': app_name,
'description': await cart.cartShortDesc(),
'prefill': {
"name": [
billingDetails.billingAddress.firstName,
billingDetails.billingAddress.lastName
].where((t) => t != null || t != "").toList().join(" "),
"method": "card",
'email': billingDetails.billingAddress.emailAddress
}
};
state.reloadState(showLoader: true);
_razorpay.open(options);
});
}

View File

@ -17,6 +17,7 @@ import 'package:label_storemax/helpers/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/pages/checkout_confirmation.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';
@ -78,6 +79,7 @@ stripePay(context,
if (order != null) {
Cart.getInstance.clear();
CheckoutSession.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(

View File

@ -113,6 +113,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1"
eventify:
dependency: transitive
description:
name: eventify
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
file:
dependency: transitive
description:
@ -357,6 +364,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
razorpay_flutter:
dependency: "direct main"
description:
name: razorpay_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
rxdart:
dependency: transitive
description:

View File

@ -1,5 +1,5 @@
# Label StoreMax
# Version 2.0.4
# Version 2.0.5
#authors: - "Anthony Gordon"
#documentation: https://woosignal.com/docs/app/ios/label-storemax
#homepage: https://woosignal.com/
@ -26,6 +26,7 @@ environment:
dependencies:
woosignal: ^1.0.8
woosignal_stripe: ^0.0.4
razorpay_flutter: ^1.2.0
wp_json_api: ^0.1.2
shared_preferences: ^0.5.6+3
cached_network_image: ^2.0.0
@ -77,6 +78,7 @@ flutter:
- assets/images/shipping_icon.png
- assets/images/dark_powered_by_stripe.png
- assets/images/cash_on_delivery.jpeg
- assets/images/razorpay.png
- lang/en.json
fonts: