arch-atlas

StripeService

core/services/stripe_service.dart

data

Overview

Two-Dio service: one (DioHelper) for backend /vendor/stripe/* endpoints, one (_stripeDio) for direct calls to api.stripe.com using the publishable key. Covers payout account get/create, bank token + add, file upload + verify identity, account/balance/transactions.

User Flow

  1. Backend reads/writes go through DioHelper → auth interceptor attaches the seller token.
  2. Stripe direct calls (tokens, file uploads) use _stripeDio with a Bearer header set to the publishable key.
  3. All methods carry a RequestTrace with feature='seller/stripe' or 'seller/balance'.
  4. Helpers (_assertSuccess) unify the throw path with friendly default messages.

Cases & Edge Cases

  • getPayoutAccount swallows 404/400/403/401 and returns null — interpreted as 'no account yet'.
  • uploadFileToStripe uses multipart/form-data; bytes are streamed from the chosen file path.
  • getBalance / getTransactions catch every error and return null/empty list — keeps the screen renderable even when partial Stripe outages occur.
  • Direct Stripe calls bypass DioHelper interceptors — no auto-retry, no logging interceptor.

Code References

  • lib/src/core/services/stripe_service.dart:17 // StripeService
  • lib/src/core/services/stripe_service.dart:43 // getPayoutAccount
  • lib/src/core/services/stripe_service.dart:77 // getStripeAccountToken
  • lib/src/core/services/stripe_service.dart:127 // createPayoutAccount
  • lib/src/core/services/stripe_service.dart:152 // getStripeBankToken
  • lib/src/core/services/stripe_service.dart:210 // uploadFileToStripe
  • lib/src/core/services/stripe_service.dart:286 // getBalance
  • lib/src/core/services/stripe_service.dart:314 // getTransactions

API Calls

  • GET/vendor/stripe/payout-accountno status

    Read the current Stripe Connect payout account state.

    Response
    PayoutAccountModel | null
    Errors
    • ·404 / 400 / 403 / 401 are swallowed as null (treated as 'no account yet')
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // initial load

    auth: seller bearer.

  • POST/vendor/stripe/payout-accountno status

    Submit Step 1 of onboarding: account_token from Stripe → backend creates the Connect account.

    Request
    { account_token: string /* ct_... */ }
    Response
    PayoutAccountModel
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // Step 1 submit

    auth: seller bearer.

  • POST/vendor/stripe/bank_accountno status

    Submit Step 2 of onboarding: bank_token from Stripe → backend attaches the bank account.

    Request
    { bank_token: string /* btok_... */ }
    Response
    { ... }
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // Step 2 submit

    auth: seller bearer.

  • POST/vendor/stripe/verify-identityno status

    Submit Step 3 of onboarding: front-of-document file id → backend submits identity to Stripe.

    Request
    { front_file_id: string /* file_... */ }
    Response
    { ... }
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // Step 3 submit

    auth: seller bearer.

  • GET/vendor/stripe/accountno status

    Refresh the full Stripe account JSON after onboarding completes.

    Response
    Stripe account JSON | null
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // refresh after step 3

    auth: seller bearer.

  • GET/vendor/stripe/balanceno status

    Available + pending balance in cents.

    Response
    BalanceModel { available, pending /* cents */ } | null
    lib/src/features/seller/balance/views/balance_screen.dart

    auth: seller bearer.

  • GET/vendor/stripe/transactionsno status

    Paginated list of seller transactions.

    Response
    { transactions: TransactionModel[] }
    lib/src/features/seller/balance/views/balance_screen.dart

    auth: seller bearer.

  • GET/vendor/stripe/transactions/:idno status

    Transaction detail (rendered in a bottom sheet).

    Response
    TransactionDetailModel | null
    lib/src/features/seller/balance/widgets/transaction_detail_sheet.dart

    auth: seller bearer.

  • POSThttps://api.stripe.com/v1/tokensno status

    Direct Stripe call (Step 1): tokenize personal account details into an account token (ct_...).

    Request
    form-urlencoded: account[individual][first_name|last_name|email|phone|dob[day|month|year]], account[individual][address][line1|city|state|postal_code|country], account[business_type], account[tos_shown_and_accepted]='true'
    Response
    { id: 'ct_...' }
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // Step 1, via stripe_service.dart:127

    auth: Bearer = STRIPE_PUBLISHABLE_KEY. Hits api.stripe.com directly.

  • POSThttps://api.stripe.com/v1/tokensno status

    Direct Stripe call (Step 2): tokenize bank account details into a bank token (btok_...).

    Request
    form-urlencoded: bank_account[country|currency|account_holder_name|account_holder_type|account_number]
    Response
    { id: 'btok_...' }
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // Step 2, via stripe_service.dart:152

    auth: Bearer = STRIPE_PUBLISHABLE_KEY.

  • POSThttps://files.stripe.com/v1/filesno status

    Direct Stripe call (Step 3): upload identity document and receive a file_id.

    Request
    FormData({ file: File, purpose: 'identity_document' })
    Response
    { id: 'file_...' }
    lib/src/features/seller/bank_account/views/bank_account_screen.dart // Step 3, via stripe_service.dart:210 // uploadFileToStripe

    auth: Bearer = STRIPE_PUBLISHABLE_KEY. Hits files.stripe.com.

Notes

Sharing a single class for direct-Stripe and backend-binding calls is convenient but fragile — separate them if Stripe rotates the publishable key shape.