Describe the bug
The initCustomerSheet method has a misleading return type (Future<CustomerSheetResult?>) that doesn't match its actual behavior or the React Native SDK implementation.
Current behavior:
- Type definition:
Future<CustomerSheetResult?> (includes paymentOption, paymentMethod, error fields)
- Actual return value: Always
null on success, throws exception on error
- React Native SDK:
Promise<{ error?: StripeError }> (error only)
The CustomerSheetResult type suggests payment option information will be returned, but it never is. This creates confusion for developers who expect to receive payment selection data from initialization.
To Reproduce
Steps to reproduce the behavior:
- Call
initCustomerSheet and check the return value:
final result = await Stripe.instance.initCustomerSheet(
customerSheetInitParams: CustomerSheetInitParams(
customerId: customerId,
customerEphemeralKeySecret: ephemeralKey,
merchantDisplayName: 'Test',
),
);
print(result); // Always null
- Call
retrieveCustomerSheetPaymentOptionSelection immediately after:
final selection = await Stripe.instance.retrieveCustomerSheetPaymentOptionSelection();
print(selection); // Can contain payment option data
- Observe that
initCustomerSheet returns null even when payment options exist, while retrieveCustomerSheetPaymentOptionSelection can retrieve them right after.
Expected behavior
The return type should match the actual behavior and align with React Native SDK:
Future<void> initCustomerSheet(...) // Throws exception on error
Smartphone / tablet
- Device: N/A (API design issue)
- OS: iOS, Android (both platforms affected)
- Package version: Current main branch
- Flutter version: All versions
Additional context
Root cause analysis:
The Flutter implementation has a misleading type definition and unnecessary complexity:
// Current implementation
Future<CustomerSheetResult?> initCustomerSheet(...) async {
final result = await _methodChannel.invokeMethod(...);
if (result is List) {
return null; // iOS case
} else {
return _parseCustomerSheetResult(result); // Android case
}
}
Issues:
- Misleading type:
CustomerSheetResult? suggests payment data might be returned, but it never is
- Unnecessary parsing: Calls
_parseCustomerSheetResult even though result is always empty on success
- Platform-specific logic: Special handling for iOS (array) vs Android (map)
Native implementations return empty values on success:
- iOS: Empty array
[]
- Android: Empty map
WritableNativeMap()
Both indicate success, but the Flutter layer treats them differently and returns null in both cases anyway.
React Native SDK comparison:
React Native correctly returns only error information:
const { error } = await CustomerSheet.initialize({...});
Source: https://stripe.dev/stripe-react-native/api-reference/variables/CustomerSheet.html
Evidence that return value is not used:
Even the official example ignores the return value:
// example/lib/screens/customer_sheet/customer_sheet_screen.dart:90
await Stripe.instance.initCustomerSheet(
customerSheetInitParams: CustomerSheetInitParams(/* ... */),
);
// No variable assignment
Proposed fix:
Future<void> initCustomerSheet(
CustomerSheetInitParams params,
) async {
final result = await _methodChannel.invokeMethod('initCustomerSheet', {
'params': params.toJson(),
'customerAdapterOverrides': {},
});
// Check for errors only
// iOS returns empty array, Android returns empty map on success - both are fine
if (result is Map<String, dynamic> && result['error'] != null) {
result['runtimeType'] = 'failed';
throw StripeException.fromJson(result);
}
}
Changes:
- Return type:
Future<CustomerSheetResult?> → Future<void>
- Simplified to error-checking only (no unnecessary parsing)
- Works with both iOS (array) and Android (map) seamlessly
- Update documentation if needed
Note: Native implementations (iOS/Android) don't need to be changed. The fix is purely on the Flutter side.
Describe the bug
The
initCustomerSheetmethod has a misleading return type (Future<CustomerSheetResult?>) that doesn't match its actual behavior or the React Native SDK implementation.Current behavior:
Future<CustomerSheetResult?>(includespaymentOption,paymentMethod,errorfields)nullon success, throws exception on errorPromise<{ error?: StripeError }>(error only)The
CustomerSheetResulttype suggests payment option information will be returned, but it never is. This creates confusion for developers who expect to receive payment selection data from initialization.To Reproduce
Steps to reproduce the behavior:
initCustomerSheetand check the return value:retrieveCustomerSheetPaymentOptionSelectionimmediately after:initCustomerSheetreturnsnulleven when payment options exist, whileretrieveCustomerSheetPaymentOptionSelectioncan retrieve them right after.Expected behavior
The return type should match the actual behavior and align with React Native SDK:
Smartphone / tablet
Additional context
Root cause analysis:
The Flutter implementation has a misleading type definition and unnecessary complexity:
Issues:
CustomerSheetResult?suggests payment data might be returned, but it never is_parseCustomerSheetResulteven though result is always empty on successNative implementations return empty values on success:
[]WritableNativeMap()Both indicate success, but the Flutter layer treats them differently and returns
nullin both cases anyway.React Native SDK comparison:
React Native correctly returns only error information:
Source: https://stripe.dev/stripe-react-native/api-reference/variables/CustomerSheet.html
Evidence that return value is not used:
Even the official example ignores the return value:
Proposed fix:
Changes:
Future<CustomerSheetResult?>→Future<void>Note: Native implementations (iOS/Android) don't need to be changed. The fix is purely on the Flutter side.