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 ## [2.0.4] - 2020-05-13
* Added Flexible widget for checkout details * 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}/flutter_web_browser/flutter_web_browser.framework",
"${BUILT_PRODUCTS_DIR}/package_info/package_info.framework", "${BUILT_PRODUCTS_DIR}/package_info/package_info.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.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}/shared_preferences/shared_preferences.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.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}/flutter_web_browser.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.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}/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}/shared_preferences.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",

View File

@ -127,6 +127,7 @@
"Done": "Done", "Done": "Done",
"Billing Details": "Billing Details", "Billing Details": "Billing Details",
"Shipping Details": "Shipping Details", "Shipping Details": "Shipping Details",
"Shipping Address": "Shipping Address",
"State": "State", "State": "State",
"Country": "Country", "Country": "Country",
"UPDATE DETAILS": "UPDATE DETAILS", "UPDATE DETAILS": "UPDATE DETAILS",
@ -145,5 +146,9 @@
"Welcome back": "Welcome back", "Welcome back": "Welcome back",
"Quantity": "Quantity", "Quantity": "Quantity",
"Select a state": "Select a state", "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/helpers/tools.dart';
import 'package:label_storemax/models/payment_type.dart'; import 'package:label_storemax/models/payment_type.dart';
import 'package:label_storemax/providers/cash_on_delivery.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'; import 'package:label_storemax/providers/stripe_pay.dart';
// Payment methods available for uses in the app // 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 // e.g. add more here
// addPayment( // addPayment(
// PaymentType( // PaymentType(
// id: 3, // id: 4,
// name: "MyNewPaymentMethod", // name: "MyNewPaymentMethod",
// desc: "Debit or Credit Card", // desc: "Debit or Credit Card",
// assetImage: "add icon image to assets/images/myimage.png", // 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.postcode = billingDetails.billingAddress.postalCode;
billing.country = billingDetails.billingAddress.country; billing.country = billingDetails.billingAddress.country;
billing.email = billingDetails.billingAddress.emailAddress; billing.email = billingDetails.billingAddress.emailAddress;
if (billingDetails.billingAddress.country == "United States") {
billing.state = billingDetails.billingAddress.state;
}
orderWC.billing = billing; orderWC.billing = billing;
@ -75,6 +78,9 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
shipping.address1 = billingDetails.shippingAddress.addressLine; shipping.address1 = billingDetails.shippingAddress.addressLine;
shipping.city = billingDetails.shippingAddress.city; shipping.city = billingDetails.shippingAddress.city;
shipping.postcode = billingDetails.shippingAddress.postalCode; shipping.postcode = billingDetails.shippingAddress.postalCode;
if (billingDetails.shippingAddress.country == "United States") {
shipping.state = billingDetails.shippingAddress.state;
}
shipping.country = billingDetails.shippingAddress.country; shipping.country = billingDetails.shippingAddress.country;
orderWC.shipping = shipping; orderWC.shipping = shipping;

View File

@ -16,7 +16,7 @@ import 'dart:ui';
Developer Notes Developer Notes
SUPPORT EMAIL - support@woosignal.com SUPPORT EMAIL - support@woosignal.com
VERSION - 2.0.4 VERSION - 2.0.5
https://woosignal.com https://woosignal.com
*/ */
@ -24,7 +24,8 @@ import 'dart:ui';
const app_name = "MyApp"; const app_name = "MyApp";
const app_key = "Your app key from WooSignal"; const app_key =
"app_b2538b4325a4a6b0f3b919f4c91cea8087ba80977f4a7c1feda669127aca";
// Your App key from WooSignal // Your App key from WooSignal
// link: https://woosignal.com/dashboard/apps // link: https://woosignal.com/dashboard/apps
@ -47,7 +48,7 @@ const app_locales_supported = [
/*<! ------ PAYMENT GATEWAYS ------!>*/ /*<! ------ PAYMENT GATEWAYS ------!>*/
// Available: "Stripe", "CashOnDelivery", // Available: "Stripe", "CashOnDelivery", "RazorPay"
// Add the method to the array below e.g. ["Stripe", "CashOnDelivery"] // Add the method to the array below e.g. ["Stripe", "CashOnDelivery"]
const app_payment_methods = ["Stripe"]; 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 "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 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 ------!>*/ /*<! ------ DEBUGGER ENABLED ------!>*/
const app_debug = true; const app_debug = true;

View File

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

View File

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

View File

@ -28,161 +28,44 @@ class CheckoutDetailsPage extends StatefulWidget {
class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> { class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
_CheckoutDetailsPageState(); _CheckoutDetailsPageState();
bool _valDifferentShippingAddress = false;
int activeTabIndex = 0;
// BILLING TEXT CONTROLLERS // BILLING TEXT CONTROLLERS
TextEditingController _txtBillingFirstName;
TextEditingController _txtBillingLastName;
TextEditingController _txtBillingAddressLine;
TextEditingController _txtBillingCity;
TextEditingController _txtBillingPostalCode;
TextEditingController _txtBillingEmailAddress;
TextEditingController _txtShippingFirstName; TextEditingController _txtShippingFirstName;
TextEditingController _txtShippingLastName; TextEditingController _txtShippingLastName;
TextEditingController _txtShippingAddressLine; TextEditingController _txtShippingAddressLine;
TextEditingController _txtShippingCity; TextEditingController _txtShippingCity;
TextEditingController _txtShippingPostalCode; TextEditingController _txtShippingPostalCode;
TextEditingController _txtShippingEmailAddress; TextEditingController _txtShippingEmailAddress;
String _strBillingCountry; String _strBillingCountry;
String _strBillingState; String _strBillingState;
String _strShippingCountry;
String _strShippingState;
var valRememberDetails = true; var valRememberDetails = true;
Widget activeTab;
@override Widget tabShippingDetails() {
void initState() { return Flexible(
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),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[ children: <Widget>[
_valDifferentShippingAddress
? Divider(
height: 0,
)
: null,
Flexible( Flexible(
child: Row( child: Row(
children: <Widget>[ 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( Flexible(
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
@ -259,7 +260,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
"\n" + "\n" +
_strBillingState _strBillingState
: trans(context, "Select state")), : trans(context, "Select state")),
action: _showSelectStateModal, action: () => _showSelectStateModal("billing"),
), ),
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
), ),
@ -275,17 +276,297 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
"\n" + "\n" +
_strBillingCountry _strBillingCountry
: trans(context, "Select country")), : trans(context, "Select country")),
action: _showSelectCountryModal, action: () => _showSelectCountryModal("billing"),
), ),
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
), ),
) ),
].where((element) => element != null).toList(), ].where((element) => element != null).toList(),
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, 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( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
@ -294,13 +575,28 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
), ),
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
), ),
height: (constraints.maxHeight - constraints.minHeight) * 0.6, height:
(constraints.maxHeight - constraints.minHeight) * 0.62,
), ),
Column( Column(
children: <Widget>[ children: <Widget>[
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, 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>[ children: <Widget>[
Text( Text(
trans(context, "Remember my details"), trans(context, "Remember my details"),
@ -317,37 +613,8 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
], ],
), ),
wsPrimaryButton(context, wsPrimaryButton(context,
title: trans(context, "USE SHIPPING ADDRESS"), title: trans(context, "USE DETAILS"),
action: () { action: () => _useDetailsTapped()),
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);
}),
], ],
), ),
], ],
@ -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/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/cart.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:label_storemax/pages/checkout_confirmation.dart';
import 'package:woosignal/models/payload/order_wc.dart'; import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart'; import 'package:woosignal/models/response/order.dart';
@ -29,6 +30,7 @@ cashOnDeliveryPay(context,
if (order != null) { if (order != null) {
Cart.getInstance.clear(); Cart.getInstance.clear();
CheckoutSession.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order); Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else { } else {
showEdgeAlertWith( 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/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart'; import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.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:label_storemax/pages/checkout_confirmation.dart';
import 'package:woosignal/models/payload/order_wc.dart'; import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart'; import 'package:woosignal/models/response/order.dart';
@ -78,6 +79,7 @@ stripePay(context,
if (order != null) { if (order != null) {
Cart.getInstance.clear(); Cart.getInstance.clear();
CheckoutSession.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order); Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else { } else {
showEdgeAlertWith( showEdgeAlertWith(

View File

@ -113,6 +113,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.1" version: "0.0.1"
eventify:
dependency: transitive
description:
name: eventify
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -357,6 +364,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.3" 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: rxdart:
dependency: transitive dependency: transitive
description: description:

View File

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