diff --git a/LabelStoreMax/CHANGELOG.md b/LabelStoreMax/CHANGELOG.md index c82afc3..7cfa957 100644 --- a/LabelStoreMax/CHANGELOG.md +++ b/LabelStoreMax/CHANGELOG.md @@ -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 diff --git a/LabelStoreMax/assets/images/razorpay.png b/LabelStoreMax/assets/images/razorpay.png new file mode 100644 index 0000000..5f85812 Binary files /dev/null and b/LabelStoreMax/assets/images/razorpay.png differ diff --git a/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj b/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj index 37eed38..1e9b492 100644 --- a/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj +++ b/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj @@ -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", diff --git a/LabelStoreMax/lang/en.json b/LabelStoreMax/lang/en.json index 0ee3efc..b80819a 100644 --- a/LabelStoreMax/lang/en.json +++ b/LabelStoreMax/lang/en.json @@ -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" } \ No newline at end of file diff --git a/LabelStoreMax/lib/app_payment_methods.dart b/LabelStoreMax/lib/app_payment_methods.dart index 7f81f0d..306649c 100644 --- a/LabelStoreMax/lib/app_payment_methods.dart +++ b/LabelStoreMax/lib/app_payment_methods.dart @@ -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 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 // ), // ), ]; diff --git a/LabelStoreMax/lib/helpers/data/order_wc.dart b/LabelStoreMax/lib/helpers/data/order_wc.dart index 80ddf22..3184bca 100644 --- a/LabelStoreMax/lib/helpers/data/order_wc.dart +++ b/LabelStoreMax/lib/helpers/data/order_wc.dart @@ -66,6 +66,9 @@ Future 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 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; diff --git a/LabelStoreMax/lib/labelconfig.dart b/LabelStoreMax/lib/labelconfig.dart index ec32f13..89a4d98 100644 --- a/LabelStoreMax/lib/labelconfig.dart +++ b/LabelStoreMax/lib/labelconfig.dart @@ -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 = [ /**/ -// 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 +/**/ +// https://razorpay.com/ + +const app_razor_id = "Your Razor ID from RazorPay"; + /**/ const app_debug = true; diff --git a/LabelStoreMax/lib/models/checkout_session.dart b/LabelStoreMax/lib/models/checkout_session.dart index 29d6fb0..d7d9f3e 100644 --- a/LabelStoreMax/lib/models/checkout_session.dart +++ b/LabelStoreMax/lib/models/checkout_session.dart @@ -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 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 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 total({bool withFormat, TaxRate taxRate}) async { diff --git a/LabelStoreMax/lib/pages/checkout_confirmation.dart b/LabelStoreMax/lib/pages/checkout_confirmation.dart index 7c395ed..daf93a9 100644 --- a/LabelStoreMax/lib/pages/checkout_confirmation.dart +++ b/LabelStoreMax/lib/pages/checkout_confirmation.dart @@ -291,14 +291,14 @@ class CheckoutConfirmationPageState extends State { .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, diff --git a/LabelStoreMax/lib/pages/checkout_details.dart b/LabelStoreMax/lib/pages/checkout_details.dart index a2a3be6..df2695d 100644 --- a/LabelStoreMax/lib/pages/checkout_details.dart +++ b/LabelStoreMax/lib/pages/checkout_details.dart @@ -28,22 +28,274 @@ class CheckoutDetailsPage extends StatefulWidget { class _CheckoutDetailsPageState extends State { _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; + + Widget tabShippingDetails() { + return Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _valDifferentShippingAddress + ? Divider( + height: 0, + ) + : null, + Flexible( + child: Row( + children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "First Name"), + controller: _txtShippingFirstName, + shouldAutoFocus: true, + ), + ), + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Last Name"), + controller: _txtShippingLastName, + ), + ), + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + ), + ), + Flexible( + child: Row( + children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Address Line"), + controller: _txtShippingAddressLine, + ), + ), + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "City"), + controller: _txtShippingCity, + ), + ), + ], + ), + ), + Flexible( + child: Row( + children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Postal code"), + controller: _txtShippingPostalCode, + ), + ), + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "Email address"), + keyboardType: TextInputType.emailAddress, + controller: _txtShippingEmailAddress), + ), + ], + ), + ), + Flexible( + child: Row( + children: [ + (_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: [ + _valDifferentShippingAddress + ? Divider( + height: 0, + ) + : null, + Flexible( + child: Row( + children: [ + 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: [ + 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: [ + 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: [ + (_strBillingCountry == "United States" + ? Flexible( + child: Padding( + child: wsSecondaryButton( + context, + title: (_strBillingState != null && + _strBillingState.isNotEmpty + ? trans(context, "Selected") + + "\n" + + _strBillingState + : trans(context, "Select state")), + action: () => _showSelectStateModal("billing"), + ), + padding: EdgeInsets.all(8), + ), + ) + : null), + Flexible( + child: Padding( + child: wsSecondaryButton( + context, + title: (_strBillingCountry != null && + _strBillingCountry.isNotEmpty + ? trans(context, "Selected") + + "\n" + + _strBillingCountry + : trans(context, "Select country")), + 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(); @@ -51,42 +303,75 @@ class _CheckoutDetailsPageState extends State { _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; - _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; + _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 sfCustomerAddress = + CustomerAddress sfCustomerBillingAddress = await CheckoutSession.getInstance.getBillingAddress(); - if (sfCustomerAddress != null) { - CustomerAddress customerAddress = sfCustomerAddress; + 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; - _strBillingState = customerAddress.state; - _strBillingCountry = customerAddress.country; + _strShippingCountry = customerAddress.country; + _strShippingState = customerAddress.state; } } - _showSelectCountryModal() { + _showSelectCountryModal(String type) { wsModalBottom( context, title: trans(context, "Select a country"), @@ -104,12 +389,24 @@ class _CheckoutDetailsPageState extends State { splashColor: Colors.grey, highlightColor: Colors.black12, onTap: () => setState(() { - _strBillingCountry = strName["name"]; - Navigator.of(context).pop(); - if (strName["code"] == "US") { - _showSelectStateModal(); - } else { - _strBillingState = ""; + 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 = ""; + } } }), ); @@ -122,7 +419,7 @@ class _CheckoutDetailsPageState extends State { ); } - _showSelectStateModal() { + _showSelectStateModal(String type) { wsModalBottom( context, title: trans(context, "Select a state"), @@ -142,8 +439,15 @@ class _CheckoutDetailsPageState extends State { splashColor: Colors.grey, highlightColor: Colors.black12, onTap: () => setState(() { - _strBillingState = strName["name"]; - Navigator.of(context).pop(); + 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(); + } }), ); }, @@ -183,109 +487,86 @@ class _CheckoutDetailsPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Flexible( - child: Row( - children: [ - Flexible( - child: wsTextEditingRow( - context, - heading: trans(context, "First Name"), - controller: _txtShippingFirstName, - shouldAutoFocus: true, - ), - ), - Flexible( - child: wsTextEditingRow( - context, - heading: trans(context, "Last Name"), - controller: _txtShippingLastName, - ), - ), - ], - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - ), - ), - Flexible( - child: Row( - children: [ - Flexible( - child: wsTextEditingRow( - context, - heading: trans(context, "Address Line"), - controller: _txtShippingAddressLine, - ), - ), - Flexible( - child: wsTextEditingRow( - context, - heading: trans(context, "City"), - controller: _txtShippingCity, - ), - ), - ], - ), - ), - Flexible( - child: Row( - children: [ - Flexible( - child: wsTextEditingRow( - context, - heading: trans(context, "Postal code"), - controller: _txtShippingPostalCode, - ), - ), - Flexible( - child: wsTextEditingRow(context, - heading: trans(context, "Email address"), - keyboardType: TextInputType.emailAddress, - controller: _txtShippingEmailAddress), - ), - ], - ), - ), - Flexible( - child: Row( - children: [ - (_strBillingCountry == "United States" - ? Flexible( - child: Padding( - child: wsSecondaryButton( - context, - title: (_strBillingState != null && - _strBillingState.isNotEmpty - ? trans(context, "Selected") + - "\n" + - _strBillingState - : trans(context, "Select state")), - action: _showSelectStateModal, + _valDifferentShippingAddress + ? Padding( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + 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), ), - padding: EdgeInsets.all(8), + 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(); + }); + }, ), ) - : null), - Flexible( - child: Padding( - child: wsSecondaryButton( - context, - title: (_strBillingCountry != null && - _strBillingCountry.isNotEmpty - ? trans(context, "Selected") + - "\n" + - _strBillingCountry - : trans(context, "Select country")), - action: _showSelectCountryModal, - ), - padding: EdgeInsets.all(8), + ].where((e) => e != null).toList(), ), + padding: EdgeInsets.symmetric(vertical: 8), ) - ].where((element) => element != null).toList(), - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - ), - ) - ], + : null, + activeTab ?? tabBillingDetails(), + ].where((e) => e != null).toList(), ), decoration: BoxDecoration( color: Colors.white, @@ -294,13 +575,28 @@ class _CheckoutDetailsPageState extends State { ), padding: EdgeInsets.all(8), ), - height: (constraints.maxHeight - constraints.minHeight) * 0.6, + height: + (constraints.maxHeight - constraints.minHeight) * 0.62, ), Column( children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + 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: [ Text( trans(context, "Remember my details"), @@ -317,37 +613,8 @@ class _CheckoutDetailsPageState extends State { ], ), 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 { ), ); } + + _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(() {}); + } } diff --git a/LabelStoreMax/lib/providers/cash_on_delivery.dart b/LabelStoreMax/lib/providers/cash_on_delivery.dart index 33a9e54..0d6ecd5 100644 --- a/LabelStoreMax/lib/providers/cash_on_delivery.dart +++ b/LabelStoreMax/lib/providers/cash_on_delivery.dart @@ -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( diff --git a/LabelStoreMax/lib/providers/razor_pay.dart b/LabelStoreMax/lib/providers/razor_pay.dart new file mode 100644 index 0000000..eda7b0d --- /dev/null +++ b/LabelStoreMax/lib/providers/razor_pay.dart @@ -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); + }); +} diff --git a/LabelStoreMax/lib/providers/stripe_pay.dart b/LabelStoreMax/lib/providers/stripe_pay.dart index 8640156..c1a8f6d 100644 --- a/LabelStoreMax/lib/providers/stripe_pay.dart +++ b/LabelStoreMax/lib/providers/stripe_pay.dart @@ -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( diff --git a/LabelStoreMax/pubspec.lock b/LabelStoreMax/pubspec.lock index 0ad3c0b..6d202b8 100644 --- a/LabelStoreMax/pubspec.lock +++ b/LabelStoreMax/pubspec.lock @@ -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: diff --git a/LabelStoreMax/pubspec.yaml b/LabelStoreMax/pubspec.yaml index 3d47e52..b72cee3 100644 --- a/LabelStoreMax/pubspec.yaml +++ b/LabelStoreMax/pubspec.yaml @@ -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: