ezet / stripe-sdk

A simple and flexible Stripe library for Flutter with complete support for SCA and PSD2.
https://pub.dev/packages/stripe_sdk
Other
137 stars 136 forks source link

Instantiating `CustomerSession` restart the `initCustomerSession` process instead of just referencing the initialised one #151

Open vinnytwice opened 2 years ago

vinnytwice commented 2 years ago

I'm using flutter_bloc for state management and initialise CustomerSession in PaymentScreen's initState() as:

class _PaymentScreenState extends State<PaymentScreen> {
  Image logo;
  @override
  void initState() {
    super.initState();
    logo = Image.asset('assets/notification.png');
    isVerified = widget.user.phoneVerified;
    try {
      PaymentMongoRepository _mongoRepository = PaymentMongoRepository();
      Stripe.init(
        Environment.stripePublishableKey,
        stripeAccount: widget.user.stripeId, // CustomerId ( buyer ), not AccountId ( seller)
        // returnUrlForSca: "stripesdk://3ds.stripesdk.io", // not existing parameter???
      );
      Future<String> createCustomerEphemeralKey(
          {String apiVersion, String customerId}) async {
        String ephemeralKey;
        await _mongoRepository
            .getEphemeralKey(
                apiVersion: apiVersion, stripeId: widget.user.stripeId)
            .then((key) {
          ephemeralKey = key;
          print(
              '∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞  PaymentScreen createCustomerEphemeralKey key is: $key');
        }).catchError((e) {
          print(
              '∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞  PaymentScreen createCustomerEphemeralKey key error: $e');
        });
        return ephemeralKey;
      }

      /// EphemeralKey needs to be in a json encoded form or you get:
      /// Unhandled Exception: Failed to parse Ephemeral Key, Please return the response as it is as you received from stripe server

      CustomerSession.initCustomerSession(
          (apiVersion) => createCustomerEphemeralKey(
              apiVersion: '2020-08-27', customerId: widget.user.stripeId),
          stripeAccount: widget.user.stripeId);
    } catch (error) {
      print('Stripe error: $error');
    }
  }
 ...

then initialise PaymentBloc which instantiate PaymentStripeRepository in which I do all the customer related operations using CustomerSession.

The problem is that when I call an operation like retrieveCustomerPaymentMethods ( the first one I do ) I get the error The provided key 'ek_test_YW*********************************************************************_******2Cdw' does not have access to account 'cus_Ku8ajLiFEsdnEB' (or that account does not exist). Application access may have been revoked. I checked and in my Stripe dashboard I have test mode enabled and the customer shows up so that's ok. The problem I found is that when I instantiate CustomerSession as below in the PaymentStripeRepository I see that my server generates another EphemeralKey and use that to carry on any operation as prints below show: flutter app:

I/flutter (14200): ∞∞∞∞∞∞∞∞∞∞ PaymentMongoRepository getEphemeralKey response is: {"message":"Ephemeral key created successfully.","data":{"id":"ephkey_1KEsPVFgRcHh7TqA7RhGjd57","object":"ephemeral_key","associated_objects":[{"type":"customer","id":"cus_Ku8ajLiFEsdnEB"}],"created":1641461849,"expires":1641465449,"livemode":false,"secret":"ek_test_YWNjdF8xRG9kS3dGZ1JjSGg3VHFBLHI1VndnN2x6SFJlZHd3VzdIZUZNS1pwTm9lRDhvSDE_00dSU5wJ9y"}}
I/flutter (14200): ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞  PaymentScreen createCustomerEphemeralKey key is: {"id":"ephkey_1KEsPVFgRcHh7TqA7RhGjd57","object":"ephemeral_key","associated_objects":[{"type":"customer","id":"cus_Ku8ajLiFEsdnEB"}],"created":1641461849,"expires":1641465449,"livemode":false,"secret":"ek_test_YWNjdF8xRG9kS3dGZ1JjSGg3VHFBLHI1VndnN2x6SFJlZHd3VzdIZUZNS1pwTm9lRDhvSDE_00dSU5wJ9y"}
I/flutter (14200): ∞∞∞∞∞∞∞∞∞∞ PaymentMongoRepository getEphemeralKey response is: {"message":"Ephemeral key created successfully.","data":{"id":"ephkey_1KEsPVFgRcHh7TqAoisvNgPe","object":"ephemeral_key","associated_objects":[{"type":"customer","id":"cus_Ku8ajLiFEsdnEB"}],"created":1641461849,"expires":1641465449,"livemode":false,"secret":"ek_test_YWNjdF8xRG9kS3dGZ1JjSGg3VHFBLHZPV0JHNDFmVmllaXFEMURZZ2pIS2FHSWdONXpDVVY_00B3UP2Cdw"}}
I/flutter (14200): ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞  PaymentScreen createCustomerEphemeralKey key is: {"id":"ephkey_1KEsPVFgRcHh7TqAoisvNgPe","object":"ephemeral_key","associated_objects":[{"type":"customer","id":"cus_Ku8ajLiFEsdnEB"}],"created":1641461849,"expires":1641465449,"livemode":false,"secret":"ek_test_YWNjdF8xRG9kS3dGZ1JjSGg3VHFBLHZPV0JHNDFmVmllaXFEMURZZ2pIS2FHSWdONXpDVVY_00B3UP2Cdw"}
I/flutter (14200): loadCart called
I/flutter (14200): PaymentStripeRepository retrieveCustomerPaymentMethods error: The provided key 'ek_test_YW*********************************************************************_******2Cdw' does not have access to account 'cus_Ku8ajLiFEsdnEB' (or that account does not exist). Application access may have been revoked.
I/flutter (14200): PaymentBloc _retrieveCustomerPaymentMethods error: The provided key 'ek_test_YW*********************************************************************_******2Cdw' does not have access to account 'cus_Ku8ajLiFEsdnEB' (or that account does not exist). Application access may have been revoked.

node server prints:

Mongoose findUser customer && stripe_version ephemeralKey is:  {
  id: 'ephkey_1KEsPVFgRcHh7TqA7RhGjd57',
  object: 'ephemeral_key',
  associated_objects: [ { type: 'customer', id: 'cus_Ku8ajLiFEsdnEB' } ],
  created: 1641461849,
  expires: 1641465449,
  livemode: false,
  secret: 'ek_test_YWNjdF8xRG9kS3dGZ1JjSGg3VHFBLHI1VndnN2x6SFJlZHd3VzdIZUZNS1pwTm9lRDhvSDE_00dSU5wJ9y'
}
Mongoose findUser customer && stripe_version ephemeralKey is:  {
  id: 'ephkey_1KEsPVFgRcHh7TqAoisvNgPe',
  object: 'ephemeral_key',
  associated_objects: [ { type: 'customer', id: 'cus_Ku8ajLiFEsdnEB' } ],
  created: 1641461849,
  expires: 1641465449,
  livemode: false,
  secret: 'ek_test_YWNjdF8xRG9kS3dGZ1JjSGg3VHFBLHZPV0JHNDFmVmllaXFEMURZZ2pIS2FHSWdONXpDVVY_00B3UP2Cdw'
}

Now this shows that calling CustomerSession.instance calls again the createCustomerEphemeralKey from CustomerSession.initCustomerSession in PaymentScreen's initState as the print I setup there only show up twice.

Why is instantiating CustomerSession restart the initCustomerSession process instead of just referencing the initialised one?? Many thanks

This is the repo:

class PaymentStripeRepository {
  Stripe stripe = Stripe.instance;
  CustomerSession customerSession = CustomerSession.instance;

  Future<List<Map<String, dynamic>>> retrieveCustomerPaymentMethods(
      {String customerId}) async {
    print('PaymentStripeRepository retrieveCustomerPaymentMethod started');
    List<Map<String, dynamic>> paymentMethods;
    await customerSession.listPaymentMethods(type: 'card').then((value) {
      if (value != null) {
        paymentMethods = jsonDecode(value['data']);
        print(
            'PaymentStripeRepository retrieveCustomerPaymentMethods list is :$paymentMethods');
      }
    }).catchError((e) {
      print('PaymentStripeRepository retrieveCustomerPaymentMethods error: $e');
      throw e;
    });
    return paymentMethods;
  }
}
ezet commented 2 years ago

Are you still having issues here? If so, I'll follow up

vinnytwice commented 2 years ago

@ezet yes, I still have this issue, is there anything O should look-up?

preteambuy commented 9 months ago

@vinnytwice can you help me out with how to tokenize the card?