// Label StoreMAX // // Created by Anthony Gordon. // Copyright © 2019 WooSignal. 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/material.dart'; import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/labelconfig.dart'; import 'package:label_storemax/widgets/woosignal_ui.dart'; import 'package:woosignal/models/response/tax_rate.dart'; import 'package:woosignal_stripe/woosignal_stripe.dart'; import 'package:woosignal/models/payload/order_wc.dart'; import 'package:woosignal/models/response/order.dart' as WS; import 'package:woosignal/woosignal.dart'; import 'dart:io'; import 'package:label_storemax/app_country_options.dart'; class CheckoutConfirmationPage extends StatefulWidget { CheckoutConfirmationPage(); @override _CheckoutConfirmationPageState createState() => _CheckoutConfirmationPageState(); } class _CheckoutConfirmationPageState extends State { _CheckoutConfirmationPageState(); bool _showFullLoader; List _taxRates; TaxRate _taxRate; @override void initState() { super.initState(); _showFullLoader = true; if (CheckoutSession.getInstance.paymentType == null) { CheckoutSession.getInstance.paymentType = arrPaymentMethods.first; } _getTaxes(); } _getTaxes() async { WooSignal wooSignal = await WooSignal.getInstance(config: wsConfig); _taxRates = await wooSignal.getTaxRates(page: 1, perPage: 100); if (CheckoutSession.getInstance.billingDetails.shippingAddress == null) { setState(() { _showFullLoader = false; }); return; } String country = CheckoutSession.getInstance.billingDetails.shippingAddress.country; Map countryMap = appCountryOptions .firstWhere((c) => c['name'] == country, orElse: () => null); if (countryMap == null) { _showFullLoader = false; setState(() {}); return; } String countryCode = countryMap["code"]; TaxRate taxRate = _taxRates.firstWhere((t) => t.country == countryCode, orElse: () => null); if (taxRate != null) { _taxRate = taxRate; } setState(() { _showFullLoader = false; }); } _actionCheckoutDetails() { Navigator.pushNamed(context, "/checkout-details").then((e) { _showFullLoader = true; _getTaxes(); }); } _actionPayWith() { Navigator.pushNamed(context, "/checkout-payment-type"); } _actionSelectShipping() { CustomerAddress shippingAddress = CheckoutSession.getInstance.billingDetails.shippingAddress; if (shippingAddress == null || shippingAddress.country == "") { showEdgeAlertWith(context, title: trans(context, "Oops"), desc: trans(context, "Add your shipping details first"), icon: Icons.local_shipping); return; } Navigator.pushNamed(context, "/checkout-shipping-type"); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, title: storeLogo(height: 50), centerTitle: true, ), resizeToAvoidBottomPadding: false, body: SafeArea( minimum: safeAreaDefault(), child: !_showFullLoader ? Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Center( child: Text(trans(context, "Checkout"), style: Theme.of(context).primaryTextTheme.subhead), ), Expanded( child: Container( padding: EdgeInsets.only(left: 10, right: 10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: wsBoxShadow()), margin: EdgeInsets.only(top: 5, bottom: 5), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ((CheckoutSession.getInstance.billingDetails .billingAddress != null) ? wsCheckoutRow(context, heading: trans( context, "Billing/shipping details"), leadImage: Icon(Icons.home), leadTitle: (CheckoutSession.getInstance .billingDetails.billingAddress .hasMissingFields() ? "Billing address is incomplete" : truncateWithEllipsis( 30, CheckoutSession.getInstance .billingDetails.billingAddress .addressFull())), action: _actionCheckoutDetails, showBorderBottom: true) : wsCheckoutRow(context, heading: trans( context, "Billing/shipping details"), leadImage: Icon(Icons.home), leadTitle: trans(context, "Add billing & shipping details"), action: _actionCheckoutDetails, showBorderBottom: true)), (CheckoutSession.getInstance.paymentType != null ? wsCheckoutRow(context, heading: trans(context, "Payment method"), leadImage: Image( image: AssetImage("assets/images/" + CheckoutSession.getInstance .paymentType.assetImage), width: 70), leadTitle: CheckoutSession .getInstance.paymentType.name, action: _actionPayWith, showBorderBottom: true) : wsCheckoutRow(context, heading: trans(context, "Pay with"), leadImage: Icon(Icons.payment), leadTitle: trans(context, "Select a payment method"), action: _actionPayWith, showBorderBottom: true)), (CheckoutSession.getInstance.shippingType != null ? wsCheckoutRow(context, heading: trans(context, "Shipping selected"), leadImage: Icon(Icons.local_shipping), leadTitle: CheckoutSession .getInstance.shippingType .getTitle(), action: _actionSelectShipping) : wsCheckoutRow(context, heading: trans(context, "Select shipping"), leadImage: Icon(Icons.local_shipping), leadTitle: trans( context, "Select a shipping option"), action: _actionSelectShipping)), ], ), ), ), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.end, children: [ Divider( color: Colors.black12, thickness: 1, ), widgetCheckoutMeta(context, title: trans(context, "Shipping fee"), amount: CheckoutSession.getInstance.shippingType == null ? trans(context, "Select shipping") : CheckoutSession.getInstance.shippingType .getTotal(withFormatting: true)), (_taxRate != null ? wsCheckoutTaxAmountWidgetFB(taxRate: _taxRate) : Container()), wsCheckoutSubtotalWidgetFB( title: trans(context, "Subtotal")), wsCheckoutTotalWidgetFB( title: trans(context, "Total"), taxRate: _taxRate), Divider( color: Colors.black12, thickness: 1, ), ], ), wsPrimaryButton(context, title: trans(context, "CHECKOUT"), action: _handleCheckout), ], ) : Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ showAppLoader(), Text(trans(context, "One moment") + "...", style: Theme.of(context).primaryTextTheme.subhead) ], ), ), ), ); } _handleCheckout() async { if (CheckoutSession.getInstance.billingDetails.billingAddress == null) { showEdgeAlertWith(context, title: trans(context, "Oops"), desc: trans(context, "Please select add your billing/shipping address to proceed"), style: EdgeAlertStyle.WARNING, icon: Icons.local_shipping); return; } if (CheckoutSession.getInstance.billingDetails.billingAddress .hasMissingFields()) { showEdgeAlertWith(context, title: trans(context, "Oops"), desc: trans(context, "Your billing/shipping details are incomplete"), style: EdgeAlertStyle.WARNING, icon: Icons.local_shipping); return; } if (CheckoutSession.getInstance.shippingType == null) { showEdgeAlertWith(context, title: trans(context, "Oops"), desc: trans(context, "Please select a shipping method to proceed"), style: EdgeAlertStyle.WARNING, icon: Icons.local_shipping); return; } if (CheckoutSession.getInstance.paymentType == null) { showEdgeAlertWith(context, title: trans(context, "Oops"), desc: trans(context, "Please select a payment method to proceed"), style: EdgeAlertStyle.WARNING, icon: Icons.payment); return; } _pay(); } Future _buildOrderWC() async { OrderWC orderWC = OrderWC(); if (Platform.isAndroid) { orderWC.paymentMethod = "Stripe - Android App"; orderWC.paymentMethodTitle = "stripe"; } else if (Platform.isIOS) { orderWC.paymentMethod = "Stripe - IOS App"; orderWC.paymentMethodTitle = "stripe"; } orderWC.setPaid = true; orderWC.status = "pending"; orderWC.currency = app_currency_iso.toUpperCase(); List lineItems = []; List cartItems = await Cart.getInstance.getCart(); cartItems.forEach((cartItem) { LineItems tmpLineItem = LineItems(); tmpLineItem.quantity = cartItem.quantity; tmpLineItem.name = cartItem.name; tmpLineItem.productId = cartItem.productId; if (cartItem.variationId != null && cartItem.variationId != 0) { tmpLineItem.variationId = cartItem.variationId; } tmpLineItem.total = cartItem.total; tmpLineItem.subtotal = cartItem.subtotal; lineItems.add(tmpLineItem); }); orderWC.lineItems = lineItems; BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails; Billing billing = Billing(); billing.firstName = billingDetails.billingAddress.firstName; billing.lastName = billingDetails.billingAddress.lastName; billing.address1 = billingDetails.billingAddress.addressLine; billing.city = billingDetails.billingAddress.city; billing.postcode = billingDetails.billingAddress.postalCode; billing.country = billingDetails.billingAddress.country; billing.email = billingDetails.billingAddress.emailAddress; orderWC.billing = billing; Shipping shipping = Shipping(); shipping.firstName = billingDetails.shippingAddress.firstName; shipping.lastName = billingDetails.shippingAddress.lastName; shipping.address1 = billingDetails.shippingAddress.addressLine; shipping.city = billingDetails.shippingAddress.city; shipping.postcode = billingDetails.shippingAddress.postalCode; shipping.country = billingDetails.shippingAddress.country; orderWC.shipping = shipping; orderWC.shippingLines = []; Map shippingLineFeeObj = CheckoutSession.getInstance.shippingType.toShippingLineFee(); if (shippingLineFeeObj != null) { ShippingLines shippingLine = ShippingLines(); shippingLine.methodId = shippingLineFeeObj['method_id']; shippingLine.methodTitle = shippingLineFeeObj['method_title']; shippingLine.total = shippingLineFeeObj['total']; orderWC.shippingLines.add(shippingLine); } if (_taxRate != null) { orderWC.feeLines = []; FeeLines feeLines = FeeLines(); feeLines.name = _taxRate.name; feeLines.total = await Cart.getInstance.taxAmount(_taxRate); feeLines.taxClass = ""; feeLines.taxStatus = "taxable"; orderWC.feeLines.add(feeLines); } return orderWC; } _pay() async { WooSignal wsStore = await WooSignal.getInstance(config: wsConfig); String cartTotal = await CheckoutSession.getInstance .total(withFormat: false, taxRate: _taxRate); FlutterStripePayment.setStripeSettings( stripeAccount: app_stripe_account, liveMode: app_stripe_live_mode); var paymentResponse = await FlutterStripePayment.addPaymentMethod(); if (paymentResponse.status == PaymentResponseStatus.succeeded) { setState(() { _showFullLoader = true; }); BillingDetails checkoutDetails = CheckoutSession.getInstance.billingDetails; Map address = { "name": checkoutDetails.billingAddress.nameFull(), "line1": checkoutDetails.shippingAddress.addressLine, "city": checkoutDetails.shippingAddress.city, "postal_code": checkoutDetails.shippingAddress.postalCode, "country": checkoutDetails.shippingAddress.country }; String cartShortDesc = await Cart.getInstance.cartShortDesc(); dynamic rsp = await wsStore.stripePaymentIntent( amount: cartTotal, email: checkoutDetails.billingAddress.emailAddress, desc: cartShortDesc, shipping: address); if (rsp == null) { showToastNetworkError(); setState(() { _showFullLoader = false; }); return false; } String clientSecret = rsp["client_secret"]; var intentResponse = await FlutterStripePayment.confirmPaymentIntent( clientSecret, paymentResponse.paymentMethodId, (double.parse(cartTotal) * 100)); if (intentResponse.status == PaymentResponseStatus.succeeded) { OrderWC orderWC = await _buildOrderWC(); WS.Order order = await wsStore.createOrder(orderWC); if (order != null) { Cart.getInstance.clear(); Navigator.pushNamed(context, "/checkout-status", arguments: order); } else { showEdgeAlertWith(context, title: trans(context, "Error"), desc: trans( context, "Something went wrong, please contact our store")); setState(() { _showFullLoader = false; }); } } else if (intentResponse.status == PaymentResponseStatus.failed) { if (app_debug) { print(intentResponse.errorMessage); } showEdgeAlertWith(context, title: trans(context, "Error"), desc: intentResponse.errorMessage); setState(() { _showFullLoader = false; }); } else { setState(() { _showFullLoader = false; }); } } } }