Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Withdrawals Laravel Package

tomatophp/filament-withdrawals

Filament Withdrawals lets you manage withdrawal methods, custom fields, and withdrawal requests directly from your Filament admin panel. Register the plugin, run the installer, and extend forms with custom field types.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation
    composer require tomatophp/filament-withdrawals
    php artisan filament-withdrawals:install
    
  2. Register Plugin Add to app/Providers/Filament/AdminPanelProvider.php:
    ->plugin(\TomatoPHP\FilamentWithdrawals\FilamentWithdrawalsPlugin::make())
    
  3. Publish Config, Assets and Migrations
    php artisan vendor:publish --tag="filament-withdrawals-config"
    php artisan vendor:publish --tag="filament-withdrawals-lang"
    php artisan vendor:publish --tag="filament-withdrawals-migrations"
    
    The config file is now effectively required if you use relation fields — see the allowlist note below.

First Use Case

Create a withdrawal method and process a request:

// Define a withdrawal method (e.g., bank transfer)
FilamentWithdrawalFormBuilder::make(1)->build();

// Submit a withdrawal request
FilamentWithdrawalFormBuilder::make(1)->send([
    'amount' => 100.50,
    'account' => '123456789',
    'currency' => 'USD',
]);

First Thing to Check After Upgrading to v5.0.1

Open config/filament-withdrawals.php and inspect the new relations key. It ships empty, so every relation field on every withdrawal method will render with no options until you populate it:

'relations' => [
    \App\Models\Bank::class => ['name'],
],

Implementation Patterns

Core Workflows

  1. Withdrawal Method Management

    • Use the built-in Filament UI to configure withdrawal methods (e.g., bank, crypto, PayPal).
    • Customize fields per method via FilamentWithdrawalFormFields::register().
  2. Request Processing

    • Frontend: Integrate a form in your app to submit withdrawal requests.
    • Backend: Validate and process via:
      $withdrawal = FilamentWithdrawalFormBuilder::make($methodId)->send($data);
      
  3. Form Field Extensions

    • Extend the form builder with custom fields (e.g., CodeEditor for verification codes):
      FilamentWithdrawalFormFields::register([
          WithdrawalFormFieldType::make('verification_code')
              ->className(TextInput::class)
              ->label('Verification Code')
              ->rules('required|digits:6'),
      ]);
      
  4. Relation Fields (v5.0.1 allowlist)

    • Relation fields are now restricted to an explicit allowlist in config/filament-withdrawals.php. Map each model to the exact columns that may be read:
      'relations' => [
          \App\Models\Bank::class   => ['name', 'iban'],
          \App\Models\Country::class => ['name', 'iso_code'],
      ],
      
    • Relationship names (e.g. 'banks' on a user model) can be allowlisted the same way instead of a foreign class.
    • The field editor in the admin panel now presents the allowlisted models and columns as selects rather than free-text class/column inputs, and validates the selection server-side — you can no longer type an arbitrary class name into the editor.
    • Keep the allowlist as narrow as the form actually needs: a column listed here is rendered into the withdrawal request form, so ['id', 'name'] is usually enough.
  5. Event-Driven Logic

    • Listen to withdrawal events (e.g., WithdrawalRequested) to trigger actions like:
      • Sending notifications.
      • Updating user balances.
      • Logging transactions.

Integration Tips

  • Laravel Cashier/Stripe: Sync withdrawal methods with payment gateways.
  • Queue Jobs: Defer processing for high-volume requests:
    WithdrawalRequest::dispatch($data)->onQueue('withdrawals');
    
  • API Endpoints: Expose withdrawal methods via API:
    Route::post('/withdraw', [WithdrawalController::class, 'store']);
    
  • Config in Deployments: treat the relations allowlist as part of your deploy artifact (env-specific config or a committed config/filament-withdrawals.php), so a fresh environment doesn't silently ship with blank relation dropdowns.

Gotchas and Tips

Pitfalls

  1. Empty Relation Allowlist After Upgrade (v5.0.1)

    • This is the upgrade trap: the allowlist defaults to empty, so existing relation fields stop showing options entirely. Nothing errors — the select just renders empty. If a withdrawal method "suddenly has no banks/countries to pick", this is why.
    • Fix by publishing the config and adding each model → columns pair used by your methods.
  2. Hidden Attributes Are Never Shown

    • Even if you list a column in the allowlist, anything in the model's $hidden array (password, remember_token, etc.) is filtered out before rendering. Don't fight it — the pre-5.0.1 behaviour of leaking a password column is exactly what was patched.
    • If a field looks empty despite being allowlisted, check $hidden and $visible on the model before assuming the config is wrong.
  3. Floating-Point Precision

    • Use bcmath or round() for currency amounts to avoid precision errors:
      $amount = bcdiv($request->amount, 1, 2); // Ensures 2 decimal places
      
  4. Migration Conflicts

    • If publishing migrations, check for column conflicts (e.g., wallet was changed from integer to float in v1.0.2).
  5. Form Field Registration

    • Ensure custom fields implement the WithdrawalFormFieldType contract. Missing methods will throw errors.
  6. Plugin Registration Order

    • Register the plugin after Filament's core resources to avoid PluginNotFoundException.

Debugging

  • Log Withdrawal Events Use Laravel's logging to trace requests:
    event(new WithdrawalRequested($data));
    
  • Validate Form Data Override the default validation rules in your provider:
    FilamentWithdrawalFormBuilder::make(1)->setRules([
        'amount' => 'required|numeric|min:0.01',
    ]);
    
  • Blank Relation Field Triage
    1. Is the method's field actually a relation field?
    2. Is the model present as a key in config('filament-withdrawals.relations')?
    3. Is the column in that model's array (not just the model listed)?
    4. Is the column in the model's $hidden/$visible exclusion set?
    5. Did the config cache get rebuilt? Run php artisan config:clear after editing.
  • Audit Old Data: after upgrading, grep your existing withdrawal method field definitions (and any seeded/demo data) for relation fields pointing at classes or columns you no longer allow — the editor will validate new input, but previously stored field configs should be reviewed.

Extension Points

  1. Custom Withdrawal Logic Override the default processing in a service provider:

    $this->app->bind(\TomatoPHP\FilamentWithdrawals\Services\Contracts\WithdrawalProcessor::class,
        \App\Services\CustomWithdrawalProcessor::class);
    
  2. Localization Publish and extend language files:

    php artisan vendor:publish --tag="filament-withdrawals-lang"
    

    Then add translations to resources/lang/{locale}/filament-withdrawals.php.

  3. Relation Allowlist as Runtime Config Because the allowlist is plain config, you can drive it from a settings table or a service provider for multi-tenant apps — but keep it server-controlled only, never user-editable, or you reintroduce the vulnerability the release fixed.

  4. Testing Use the package's test utilities to mock withdrawals:

    $this->actingAs($user)
         ->post('/withdraw', ['method_id' => 1, 'amount' => 100.00]);
    $this->assertDatabaseHas('withdrawal_requests', ['amount' => 100.00]);
    

    Add a regression test asserting a non-allowlisted relation field renders no options and a hidden column (password) is absent from the rendered form.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console