flutter-stripe / flutter_stripe

Flutter SDK for Stripe.
https://pub.dev/packages/flutter_stripe
948 stars 524 forks source link

Throws Card details not complete #672

Closed imrishuroy closed 2 years ago

imrishuroy commented 2 years ago

I am testing on an android device sometimes it works, but most of the time it gives this error StripeException(error: LocalizedErrorMessage(code: FailureCode.Failed, localizedMessage: Card details not complete, message: Card details not complete, stripeErrorCode: null, declineCode: null, type: null))

and my payment method log

PaymentMethod(id: pm_*****, livemode: false, type: Card, billingDetails: BillingDetails(email: null, address: Address(city: null, country: null, line1: null, line2: null, postalCode: null, state: null), phone: null, name: null), card: Card(brand: Visa, country: US, expYear: 2024, expMonth: 12, funding: credit, last4: 4242), sepaDebit: SepaDebit(country: null, bankCode: null, fingerprint: null, last4: null), bacsDebit: BacsDebit(sortCode: null, fingerprint: null, last4: null), auBecsDebit: AuBecsDebit(fingerprint: null, last4: null, bsbNumber: null), sofort: Sofort(country: null), ideal: Ideal(bankIdentifierCode: null, bank: null), fpx: Fpx(bank: null, accountHolderType: null), upi: Upi(vpa: null), customerId: null)

also cvc and card number is printing null

remonh87 commented 2 years ago

I would recommend to add a CardEditController to the field and see if the all the data is updated correctly. Can you add the value of controller.details to this ticket (if you are not using test card you can anonymise the card).

See https://github.com/flutter-stripe/flutter_stripe/blob/893a8449765af4d135a6737bdef1b53e5e6afa63/example/lib/screens/card_payments/no_webhook_payment_screen.dart#L19

imrishuroy commented 2 years ago

Here are card details printed on the console from controller.details

CardFieldInputDetails(complete: true, last4: 6927, expiryMonth: 12, expiryYear: 24, postalCode: null, brand: MasterCard, number: null, cvc: null, validExpiryDate: CardValidationState.Valid, validCVC: CardValidationState.Valid, validNumber: CardValidationState.Valid)

remonh87 commented 2 years ago

I cannot reproduce it on my side can you provide us a reproduction example so we can triage the issue?

kwstasarva commented 2 years ago

Hello @remonh87 . We are facing the same issue. For what it's worth, we are using BLOC as our state management solution. The issue only occurs on Android. We are using a cardEditController in our UI and then we try to confirm the payment within our BLOC. The details of the card are complete, however when we try to process the payment, a stripe exception occurs:

StripeException(error: LocalizedErrorMessage(code: FailureCode.Failed, localizedMessage: Card details not complete, message: Card details not complete, stripeErrorCode: null, declineCode: null, type: null))

And further below this:

WARNING! Initial card data value has been ignored. Handling card data manually will break PCI compliance provided by Stripe. Please make sure you understand the severe consecuences of it. [https://stripe.com/docs/security/guide#validating-pci-compliance](). To handle PCI compliance yourself and allow to edit card data programatically,set dangerouslyGetFullCardDetails: true

We do not handle the card data on our own though.

remonh87 commented 2 years ago

@kwstasarva we really need a GIST or repository containing some code where we can reproduce the issue. If this is not possible I am afraid I have to close this issue. I spent quite some time trying to find it but no success. Hopefully you can provide something to us.

kwstasarva commented 2 years ago

Since we are working on a production application in a private repo, would it be possible for you to arrange a brief call to go through the code and have a look at the issue? Because it would be difficult to create a new repo to repro the issue. If not, I will do my best to provide a GIST. Thank you @remonh87

adlion commented 2 years ago

Same issue using riverpod. Card details are correct and pass validations. The moment you trigger Stripe.instance.confirmPayment( ...) is showing the card details are not correct.

kwstasarva commented 2 years ago

@remonh87 Please let me know of a way we can contact each other so I can help in any way to resolve the issue :)

adlion commented 2 years ago

By investigating further I found out if you put the card element in provider states it will throw the upmentioned error. If you keep the card element outside the riverpod states is working correctly. I was wondering what will happen if I put Stripe in a Statenotifier and manage its state from there. I suppose it might work but have not tried yet due to some deadlines with current project.

remonh87 commented 2 years ago

@kwstasarva feel free to send a me a dm on twitter or linkedin.

kwstasarva commented 2 years ago

@remonh87 Unfortunately I cannot message you in any platform. All I am getting is "This user can't be messaged"

fernan542 commented 2 years ago

@remonh87 Unfortunately I cannot message you in any platform. All I am getting is "This user can't be messaged"

Try to add a property in your bloc state that will handle the changes from the card.

class AddPaymentMethodState extends Equatable {
  const AddPaymentMethodState({
    this.details = const CardFieldInputDetails(complete: false),
    this.status = EventStatus.initial,
    this.errorMessage,
  });
  final CardFieldInputDetails details;
  final EventStatus status;
  final String? errorMessage;
  @override
  List<Object?> get props => [details, status, errorMessage];

  AddPaymentMethodState copyWith({
    CardFieldInputDetails? details,
    EventStatus? status,
    String? errorMessage,
  }) {
    return AddPaymentMethodState(
      details: details ?? this.details,
      status: status ?? this.status,
      errorMessage: errorMessage ?? this.errorMessage,
    );
  }

  @override
  String toString() {
    return ''' AddPaymentMethodState: { details: ${details.complete}, status: $status, error: $errorMessage } ''';
  }
}

Then on your UI:

 CardFormField(
              enablePostalCode: true,
              backgroundColor: Colors.white,
              onCardChanged: (details) => context
                  .read<AddPaymentMethodCubit>()
                  .onDetailsChanged(details),
            ),

This way you can check if the CardFieldInputDetails is really completed via logs.

remonh87 commented 2 years ago

yes the above solution of @fernan542 is correct.

Keep in mind The UI elements are not flutter UI objects but native objects (due to PCI compliance we have to use Stripe sdk elements) and all data must be updated through the methodchannels. I would really recommend to stick to our example implementations of the Cardfield and Cardformfield. use the listeners on either the controller or the onCardChanged callback to determine whether or not the details are complete. It is fine to update BLOC or Riverpod based on these callbacks .

kwstasarva commented 2 years ago

@fernan542 This is exactly what I am doing as well. However when I call

final paymentIntent = await paymentClient.confirmPayment(
        paymentIntentClientSecret: initStripePayment.stripeToken,
        data: PaymentMethodParams.card(
          //only when customer accepts future usage
          setupFutureUsage: state.saveCardForFutureUsage.value
              ? PaymentIntentsFutureUsage.OffSession
              : null,
        ),
      );

I am still getting the same error as above. I believe there is something wrong with the instance of the card when used within the BLOC.

Note: The paymentClient is an instance of Stripe.

remonh87 commented 2 years ago

closing this for now. feel free to reopen it when there is a reproduction scenario so we can debug the specifics.

Inventrohyder commented 2 years ago

We are also getting the same error

StripeException(error: LocalizedErrorMessage(code: FailureCode.Failed, localizedMessage: Card details not complete, message: Card details not complete, stripeErrorCode: null, declineCode: null, type: null))

However, downgrading to flutter_stripe 2.4.0 fixes the issue

The error only happens for android

HatsuneMikuV commented 2 years ago

We are also getting the same error(Stripe 5.0 & 4.0), Everything works fine on ios

{complete: true, last4: 8600, expiryMonth: 7, expiryYear: 2024, postalCode: , brand: Visa, number: null, cvc: null, validExpiryDate: Unknown, validCVC: Unknown, validNumber: Unknown}

[log] confirmPayment error: StripeException(error: LocalizedErrorMessage(code: FailureCode.Failed, localizedMessage: Card details not complete, message: Card details not complete, stripeErrorCode: null, declineCode: null, type: null))

ydag commented 2 years ago

StripeException(error: LocalizedErrorMessage(code: FailureCode.Failed, localizedMessage: Card details not complete, message: Card details not complete, stripeErrorCode: null, declineCode: null, type: null))

(Only for Android as well)

I am also having the same issue, I think this issue is not resolved yet @imrishuroy , @kwstasarva ? Could you open again @remonh87 ? Might be something related with android platform implementation since it works for iOS.

kwstasarva commented 2 years ago

@ydag Are you using a state management library? BLOC, Riverpod or something? What I did to resolve my issue back then, was to move all the payment logic in the UI layer and not in our BLOCs. Can you check if this helps you?

ydag commented 2 years ago

@kwstasarva

Yes, I am using bloc as well. But the weird thing is it works on iOS. So not sure if it is related with state management solution?

kwstasarva commented 2 years ago

@ydag I can't be sure either. When I moved the logic in the UI, it works fine for both platforms.

ydag commented 2 years ago

Alright, thanks for your answer. @kwstasarva But I think this can be investigated further since we should be able to use with bloc as well. I still found it really interesting since it works on iOS.

kwstasarva commented 2 years ago

@ydag I did not spend any more time looking into the issue to be honest. If you find a solution, please ping me. I am curious to know what the issue was

ydag commented 1 year ago

@remonh87 Could you reopen this issue? I am still having it with 5.1.0.

AlexChalakov commented 1 year ago

Can confirm the problem still occurs on android with flutter_stripe: ^7.0.0

remonh87 commented 1 year ago

Like said before please provide us with a reproduction scenario so we can fix it in the library.

ShaowenSu commented 1 year ago

To everyone who is stuck with this issue, DO NOT dispose (close) of the card field until the payment is confirmed.

ShaowenSu commented 1 year ago

@ydag I did not spend any more time looking into the issue to be honest. If you find a solution, please ping me. I am curious to know what the issue was

DO NOT close the card field until the payment is confirmed.

Minch909 commented 1 year ago

@ydag I did not spend any more time looking into the issue to be honest. If you find a solution, please ping me. I am curious to know what the issue was

DO NOT close the card field until the payment is confirmed.

I still get this error even if I dont close the card field