import 'package:flutter/material.dart'; import 'package:stripe_sdk/stripe_sdk.dart'; import 'package:stripe_sdk/stripe_sdk_ui.dart'; import '../../constants.dart'; import '../../events/eventbus.dart'; import '../../events/events.dart'; import '../../generated/l10n.dart'; import '../../models/order.dart'; import '../../models/payment_platform.dart'; import '../../models/stripe_payment_method.dart'; import '../../routes.dart'; import '../../store/actions.dart'; import '../../store/store.dart'; import '../../utils/utils.dart'; import '../../widgets/general/breadcrumbs.dart'; import '../../widgets/general/navigationbar.dart'; class DesktopStripePayWeb extends StatefulWidget { final Key key; final Order order; final PaymentPlatform paymentPlatform; final StripePaymentMethod stripePaymentMethod; const DesktopStripePayWeb(this.order, this.paymentPlatform, {this.key, this.stripePaymentMethod}); @override State createState() { return DesktopStripePayWebState(); } } class DesktopStripePayWebState extends State { GlobalKey _scaffoldKey = GlobalKey(); final formKey = GlobalKey(); final card = StripeCard(); CardForm form; bool isSubmitting; double sideSpace = 0; double mainSpace = 1200; @override Widget build(BuildContext context) { store.dispatch(UpdateContext(context)); if (MediaQuery.of(context).size.width <= 1200) { mainSpace = MediaQuery.of(context).size.width; sideSpace = 0; } else { mainSpace = 1200; sideSpace = (MediaQuery.of(context).size.width - 1200) / 2; } Widget body = Center( child: Icon( Icons.credit_card, size: 40.0, color: Colors.black26, ), ); if (widget.stripePaymentMethod == null) { form = CardForm(card: card, formKey: formKey, displayPostalCode: false,); body = ListView( children: [ form, Container( padding: EdgeInsets.only(top: 20.0, bottom: 20.0, right: 16.0), alignment: Alignment.centerRight, child: ElevatedButton( style: ElevatedButton.styleFrom( primary: Theme.of(context).primaryColor, ), child: Text( S.of(context).submit, style: TextStyle( color: Colors.white, ), ), onPressed: () { if (formKey.currentState.validate()) { formKey.currentState.save(); _paymentRequestWithCard(context); } else { ScaffoldMessenger.of(context).showSnackBar( messageSnackBar( context, S.of(context).this_credit_card_is_invalid ) ); } }, ), ), ], ); } WidgetsBinding.instance.addPostFrameCallback((timeStamp) { if (widget.stripePaymentMethod != null) { _paymentWithPaymentMethod(context); } }); return Scaffold( key: _scaffoldKey, appBar: MiniNavigationBar( title: S.of(context).blog, back: true, breadCrumbs: [ BreadCrumb(S.of(context).add_credit_card, null), ], breadCrumbHeight: Constants.BREADCRUMB_HEIGHT, ), body: Row( children: [ Container(width: sideSpace,), Expanded(child: body,), Container(width: sideSpace,), ], ), ); } @override void initState() { super.initState(); isSubmitting = false; StripeApi.init(widget.paymentPlatform.publishableKey); } SnackBar messageSnackBar(BuildContext context, String message) { Column column = Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [Text( message, style: TextStyle( color: Colors.white, ), )], ); return SnackBar( content: Container( height: 45.0, child: column, ), action: SnackBarAction( label: S.of(context).ok, onPressed: () { ScaffoldMessenger.of(context).hideCurrentSnackBar(); }, ), ); } _paymentWithPaymentMethod(BuildContext context) async { Utils.stripePaymentIntent(widget.order, widget.stripePaymentMethod.customerId, widget.stripePaymentMethod.paymentMethodId, widget.stripePaymentMethod.paymentMethodType, (response) async { if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) { await StripeApi.instance.confirmPaymentIntent( response.data[Constants.STRIPE_CLIENT_SECRET], data: { 'payment_method': response.data['payment_method'], }, ).then((result2) { if (result2['status'] == Constants.STRIPE_STATUS_SUCCEDED) { Utils.stripeChargedSuccess(widget.order, widget.stripePaymentMethod.paymentMethodId, result2['id'], (response) { if (isSubmitting) { Navigator.of(context).pop(); } eventBus.fire(OnOrderUpdated()); Routes.router.navigateTo(context, '/orderdetail/${widget .order.id}', replace: true); }, (showErrorDialog) ); } else { showErrorDialog(Exception('Unknown error')); } }).catchError(showErrorDialog); } }, (showErrorDialog)); isSubmitting = true; Utils.showSubmitDialog(context); } _paymentRequestWithCard(BuildContext context) async { isSubmitting = true; Utils.showSubmitDialog(context); await StripeApi.instance.createPaymentMethodFromCard(card) .then((result) { Utils.stripePaymentIntent(widget.order, null, result['id'], result['type'], (response) async { if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) { await StripeApi.instance.confirmPaymentIntent( response.data[Constants.STRIPE_CLIENT_SECRET], data: { 'payment_method': response.data['payment_method'], } ).then((result2) { if (result2['status'] == Constants.STRIPE_STATUS_SUCCEDED) { Utils.stripeChargedSuccess(widget.order, result['id'], // payment method id result2['id'], (response) { // payment intent id if (isSubmitting) { Navigator.of(context).pop(); } eventBus.fire(OnOrderUpdated()); Routes.router.navigateTo(context, '/orderdetail/${widget .order.id}', replace: true); }, (showErrorDialog) ); } else { showErrorDialog(Exception('Unknown error')); } }).catchError(showErrorDialog); } }, (showErrorDialog), cardBrand: result['card']['brand'], cardCountry: result['card']['country'], cardExpMonth: result['card']['exp_month'], cardExpYear: result['card']['exp_year'], cardFunding: result['card']['funding'], cardLast4: result['card']['last4'], ); }).catchError(showErrorDialog); } void showErrorDialog(dynamic error) { if (isSubmitting) { Navigator.of(context).pop(); isSubmitting = false; } Utils.showMessageDialog(context, error, onOk: () { Navigator.of(context).pop(); Navigator.of(context).pop(); }); } }