Skip to content

feat: add Stripe Identity Verification support#2318

Closed
realmeylisdev wants to merge 3 commits into
flutter-stripe:mainfrom
realmeylisdev:feature/identity-verification-1819
Closed

feat: add Stripe Identity Verification support#2318
realmeylisdev wants to merge 3 commits into
flutter-stripe:mainfrom
realmeylisdev:feature/identity-verification-1819

Conversation

@realmeylisdev
Copy link
Copy Markdown
Contributor

Summary

This PR adds support for Stripe Identity Verification, allowing Flutter apps to verify users' government-issued IDs and selfies using Stripe's native IdentityVerificationSheet.

Closes #1819

API Usage

final result = await Stripe.instance.presentIdentityVerificationSheet(
  verificationSessionId: 'vs_xxx',
  ephemeralKeySecret: 'ek_xxx',
  brandLogo: 'base64EncodedImage', // Optional, iOS only
);

switch (result) {
  case IdentityVerificationCompleted():
    print('Verification completed');
  case IdentityVerificationCanceled():
    print('User canceled');
  case IdentityVerificationFailed(:final error):
    print('Error: ${error.message}');
}

Changes

Platform Interface Layer

  • Add IdentityVerificationSheetParams, IdentityVerificationResult (sealed class), and IdentityVerificationError models using Freezed
  • Add presentIdentityVerificationSheet abstract method to StripePlatform
  • Implement method channel communication in MethodChannelStripe

iOS Implementation

  • Add StripeIdentity dependency to Package.swift
  • Create StripeSdkImpl+Identity.swift extension with native implementation
  • Support optional brand logo via base64 encoded image

Android Implementation

  • Add com.stripe:identity dependency to build.gradle
  • Create IdentityVerificationSheetManager following the StripeUIManager pattern
  • Register method in StripeSdkModule and StripeAndroidPlugin

Web

  • Add stub that throws WebUnsupportedError (Identity Verification requires native mobile SDKs)

Example App

  • Add IdentityVerificationScreen with demo implementation

API Compatibility

Feature Stripe iOS SDK Stripe Android SDK This Implementation
Method IdentityVerificationSheet.present() IdentityVerificationSheet.present() presentIdentityVerificationSheet()
verificationSessionId
ephemeralKeySecret
brandLogo ✅ (UIImage) ✅ (Uri) ✅ (base64, iOS only)
Result: Completed .flowCompleted Completed IdentityVerificationCompleted
Result: Canceled .flowCanceled Canceled IdentityVerificationCanceled
Result: Failed .flowFailed(error) Failed(throwable) IdentityVerificationFailed(error)

Note on React Native

The original issue mentions "React native supports it" - however, after investigation, React Native Stripe SDK appears to have verifyIdentity only as part of the Onramp feature, not as a standalone Identity Verification Sheet. This implementation provides the full native Identity Verification Sheet functionality that matches the official Stripe iOS and Android SDKs directly.

Test Plan

  • iOS: Identity sheet presents correctly
  • iOS: User can complete verification flow
  • iOS: Cancellation returns correct result
  • iOS: Errors are properly propagated
  • Android: Identity sheet presents correctly
  • Android: User can complete verification flow
  • Android: Cancellation returns correct result
  • Android: Errors are properly propagated
  • Web: Throws appropriate unsupported error

Testing Requirements

  • Requires a backend endpoint that creates a VerificationSession and returns {id, ephemeral_key_secret}
  • Identity must be enabled in Stripe Dashboard
  • Real device recommended for camera-based verification (not simulator)
  • Camera permissions must be configured (NSCameraUsageDescription on iOS)

Add support for Stripe Identity Verification, allowing Flutter apps to verify
users' government-issued IDs and selfies using Stripe's native IdentityVerificationSheet.

## API Usage

```dart
final result = await Stripe.instance.presentIdentityVerificationSheet(
  verificationSessionId: 'vs_xxx',
  ephemeralKeySecret: 'ek_xxx',
  brandLogo: 'base64EncodedImage', // Optional, iOS only
);

switch (result) {
  case IdentityVerificationCompleted():
    print('Verification completed');
  case IdentityVerificationCanceled():
    print('User canceled');
  case IdentityVerificationFailed(:final error):
    print('Error: ${error.message}');
}
```

## Changes

### Platform Interface
- Add `IdentityVerificationSheetParams`, `IdentityVerificationResult`, and `IdentityVerificationError` models
- Add `presentIdentityVerificationSheet` method to platform interface

### iOS
- Add `StripeIdentity` dependency to Package.swift
- Add `StripeSdkImpl+Identity.swift` extension with native implementation

### Android
- Add `com.stripe:identity` dependency to build.gradle
- Add `IdentityVerificationSheetManager` for handling the verification flow

### Web
- Add stub that throws `WebUnsupportedError` (Identity requires native SDKs)

### Example App
- Add `IdentityVerificationScreen` demo

Closes flutter-stripe#1819
@realmeylisdev
Copy link
Copy Markdown
Contributor Author

@remonh87 - This PR implements the Stripe Identity Verification feature requested in #1819.

Would you be able to review when you have a chance?

Note about CI: The 16 test failures in stripe_js are unrelated to this PR - they occur because GitHub Actions doesn't pass repository secrets (STRIPE_PUBLISHABLE_KEY) to PRs from forks. The same tests fail on other fork PRs (e.g., #2317, #2316) and pass when run from the main repo.

Thanks!

- Add .build directory to iOS gitignore
- Update Package.resolved for StripeIdentity dependency
- Regenerate payment_sheet.g.dart (LinkDisplay enum fix)
@jonasbark
Copy link
Copy Markdown
Member

Thanks for this PR!

We currently synchronize our code base with the one from Stripe React Native. Most of your Android / iOS changes would be overwritten then.

There are a few possible ways to go ahead:

  1. create an extra package similar to https://github.com/stripe/stripe-identity-react-native
  2. or move the changes from the synchronized classes to e.g. an extension function of their respective classes

Since it introduces another library dependency, I would opt for variant 1)

@realmeylisdev
Copy link
Copy Markdown
Contributor Author

Thanks for the guidance @jonasbark!

I've created a new PR #2319 with the separate package approach following the stripe-identity-react-native pattern.

The new structure keeps Identity completely isolated from the main package:

  • Separate method channel (flutter.stripe_identity/identity)
  • Standalone native plugins (won't be affected by React Native sync)
  • Independent versioning

Closing this PR in favor of #2319.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Stripe identity verification

2 participants