93a69dd826
PaymentSettings: - New "🇲🇩 Paynet" section: enabled toggle, mode (test/live), merchant_code, service_id, user, password, secret (HMAC), webhook URL hint - Webhook URL: https://service.mir.md/payments/paynet/webhook PaymentController: - startPaynet() — builds Paynet redirect (stub mode prints flow) - paynetWebhook() — verifies HMAC-SHA256 signature canonical Merchant_Code|Order_ID|Amount|Status, marks subscription paid on Status=OK, matches by invoice_number = Order_ID - availableMethods() includes paynet Tenant /billing: - 4th payment button "🇲🇩 Paynet" — visible only when configured. Description: Card MAIB / MICB / Victoriabank, MD Cash, e-money Routes: - POST /payments/paynet/webhook (CSRF excluded)
278 lines
15 KiB
PHP
278 lines
15 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Central\Pages;
|
|
|
|
use App\Models\Central\PlatformSetting;
|
|
use Filament\Forms;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Schemas;
|
|
use Filament\Schemas\Components\Utilities\Get;
|
|
use Filament\Schemas\Schema;
|
|
|
|
class PaymentSettings extends Page
|
|
{
|
|
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-credit-card';
|
|
|
|
protected static ?string $navigationLabel = 'Setări plăți';
|
|
|
|
protected static ?string $title = 'Integrări de plată';
|
|
|
|
protected static ?int $navigationSort = 90;
|
|
|
|
protected string $view = 'filament.central.pages.payment-settings';
|
|
|
|
public ?array $data = [];
|
|
|
|
public function mount(): void
|
|
{
|
|
$s = PlatformSetting::many([
|
|
'payments.stripe', 'payments.paypal', 'payments.paynet', 'payments.bank',
|
|
'payments.platform_currency', 'payments.invoice_prefix',
|
|
'payments.terms', 'payments.company_legal',
|
|
]);
|
|
|
|
$stripe = $s['payments.stripe'] ?? [];
|
|
$paypal = $s['payments.paypal'] ?? [];
|
|
$paynet = $s['payments.paynet'] ?? [];
|
|
$bank = $s['payments.bank'] ?? [];
|
|
$legal = $s['payments.company_legal'] ?? [];
|
|
|
|
$this->form->fill([
|
|
'platform_currency' => $s['payments.platform_currency'] ?? 'MDL',
|
|
'invoice_prefix' => $s['payments.invoice_prefix'] ?? 'INV',
|
|
'terms' => $s['payments.terms'] ?? 'Plata se efectuează în 7 zile de la emitere. Pentru întârzieri se aplică penalități 0.1%/zi.',
|
|
|
|
'legal_name' => $legal['name'] ?? null,
|
|
'legal_idno' => $legal['idno'] ?? null,
|
|
'legal_address' => $legal['address'] ?? null,
|
|
'legal_phone' => $legal['phone'] ?? null,
|
|
'legal_email' => $legal['email'] ?? null,
|
|
|
|
'stripe_enabled' => $stripe['enabled'] ?? false,
|
|
'stripe_mode' => $stripe['mode'] ?? 'test',
|
|
'stripe_publishable' => $stripe['publishable_key'] ?? null,
|
|
'stripe_secret' => $stripe['secret_key'] ?? null,
|
|
'stripe_webhook' => $stripe['webhook_secret'] ?? null,
|
|
|
|
'paypal_enabled' => $paypal['enabled'] ?? false,
|
|
'paypal_mode' => $paypal['mode'] ?? 'sandbox',
|
|
'paypal_client_id' => $paypal['client_id'] ?? null,
|
|
'paypal_secret' => $paypal['secret'] ?? null,
|
|
|
|
'paynet_enabled' => $paynet['enabled'] ?? false,
|
|
'paynet_mode' => $paynet['mode'] ?? 'test',
|
|
'paynet_merchant_code' => $paynet['merchant_code'] ?? null,
|
|
'paynet_service_id' => $paynet['service_id'] ?? null,
|
|
'paynet_user' => $paynet['user'] ?? null,
|
|
'paynet_password' => $paynet['password'] ?? null,
|
|
'paynet_secret' => $paynet['secret'] ?? null,
|
|
|
|
'bank_enabled' => $bank['enabled'] ?? true,
|
|
'bank_iban' => $bank['iban'] ?? null,
|
|
'bank_bic' => $bank['bic'] ?? null,
|
|
'bank_name' => $bank['bank_name'] ?? null,
|
|
'bank_beneficiary' => $bank['beneficiary'] ?? null,
|
|
'bank_instructions' => $bank['instructions'] ?? null,
|
|
]);
|
|
}
|
|
|
|
public function form(Schema $schema): Schema
|
|
{
|
|
return $schema
|
|
->components([
|
|
Schemas\Components\Section::make('General')
|
|
->columns(3)
|
|
->schema([
|
|
Forms\Components\Select::make('platform_currency')
|
|
->label('Monedă platformă')
|
|
->options(['MDL' => 'MDL', 'EUR' => 'EUR', 'USD' => 'USD'])
|
|
->required(),
|
|
Forms\Components\TextInput::make('invoice_prefix')
|
|
->label('Prefix facturi')->maxLength(10)->default('INV'),
|
|
Forms\Components\Textarea::make('terms')
|
|
->label('Termeni de plată')->rows(2)->columnSpanFull(),
|
|
]),
|
|
Schemas\Components\Section::make('Date legale (apar pe facturi)')
|
|
->columns(2)
|
|
->schema([
|
|
Forms\Components\TextInput::make('legal_name')->label('Denumire companie')->maxLength(160),
|
|
Forms\Components\TextInput::make('legal_idno')->label('IDNO / CUI')->maxLength(40),
|
|
Forms\Components\TextInput::make('legal_address')->label('Adresă')->columnSpanFull()->maxLength(255),
|
|
Forms\Components\TextInput::make('legal_phone')->label('Telefon')->tel()->maxLength(40),
|
|
Forms\Components\TextInput::make('legal_email')->label('Email')->email()->maxLength(120),
|
|
]),
|
|
Schemas\Components\Section::make('💳 Stripe')
|
|
->description('Procesare carduri online. Funcționează în 30+ țări. Comision ~2.9% + 0.30€/tranzacție.')
|
|
->columns(3)
|
|
->collapsible()
|
|
->collapsed(fn (Get $get) => ! $get('stripe_enabled'))
|
|
->schema([
|
|
Forms\Components\Toggle::make('stripe_enabled')->label('Activează Stripe')->default(false)->live(),
|
|
Forms\Components\Select::make('stripe_mode')
|
|
->label('Mod')
|
|
->options(['test' => '🧪 Test', 'live' => '🟢 Live'])
|
|
->default('test')
|
|
->required(fn (Get $get) => $get('stripe_enabled'))
|
|
->visible(fn (Get $get) => $get('stripe_enabled')),
|
|
Forms\Components\TextInput::make('stripe_publishable')
|
|
->label('Publishable key')->placeholder('pk_test_...')
|
|
->visible(fn (Get $get) => $get('stripe_enabled')),
|
|
Forms\Components\TextInput::make('stripe_secret')
|
|
->label('Secret key')->password()->revealable()->placeholder('sk_test_...')
|
|
->visible(fn (Get $get) => $get('stripe_enabled')),
|
|
Forms\Components\TextInput::make('stripe_webhook')
|
|
->label('Webhook secret')->password()->revealable()->placeholder('whsec_...')
|
|
->columnSpanFull()
|
|
->helperText('Endpoint webhook: https://service.mir.md/payments/stripe/webhook')
|
|
->visible(fn (Get $get) => $get('stripe_enabled')),
|
|
]),
|
|
Schemas\Components\Section::make('🅿️ PayPal')
|
|
->description('Plăți internaționale. Mai potrivit pentru clienți din afara MD.')
|
|
->columns(3)
|
|
->collapsible()
|
|
->collapsed(fn (Get $get) => ! $get('paypal_enabled'))
|
|
->schema([
|
|
Forms\Components\Toggle::make('paypal_enabled')->label('Activează PayPal')->default(false)->live(),
|
|
Forms\Components\Select::make('paypal_mode')
|
|
->label('Mod')
|
|
->options(['sandbox' => '🧪 Sandbox', 'live' => '🟢 Live'])
|
|
->default('sandbox')
|
|
->visible(fn (Get $get) => $get('paypal_enabled')),
|
|
Forms\Components\Placeholder::make('paypal_webhook_info')
|
|
->label('Webhook')
|
|
->content('https://service.mir.md/payments/paypal/webhook')
|
|
->visible(fn (Get $get) => $get('paypal_enabled')),
|
|
Forms\Components\TextInput::make('paypal_client_id')
|
|
->label('Client ID')->placeholder('AYS...')
|
|
->visible(fn (Get $get) => $get('paypal_enabled')),
|
|
Forms\Components\TextInput::make('paypal_secret')
|
|
->label('Secret')->password()->revealable()->placeholder('EJk...')
|
|
->visible(fn (Get $get) => $get('paypal_enabled')),
|
|
]),
|
|
Schemas\Components\Section::make('🇲🇩 Paynet (Moldova)')
|
|
->description('Procesator de plăți Moldova. Acceptă carduri MAIB, MICB, Victoriabank, OTP, MD Cash, Bitcoin, e-money. Comision negociabil ~1.8-2.5%.')
|
|
->columns(3)
|
|
->collapsible()
|
|
->collapsed(fn (Get $get) => ! $get('paynet_enabled'))
|
|
->schema([
|
|
Forms\Components\Toggle::make('paynet_enabled')->label('Activează Paynet')->default(false)->live(),
|
|
Forms\Components\Select::make('paynet_mode')
|
|
->label('Mod')
|
|
->options(['test' => '🧪 Test', 'live' => '🟢 Live'])
|
|
->default('test')
|
|
->visible(fn (Get $get) => $get('paynet_enabled')),
|
|
Forms\Components\Placeholder::make('paynet_webhook_info')
|
|
->label('Webhook (Notify URL)')
|
|
->content('https://service.mir.md/payments/paynet/webhook')
|
|
->visible(fn (Get $get) => $get('paynet_enabled')),
|
|
Forms\Components\TextInput::make('paynet_merchant_code')
|
|
->label('Merchant Code')
|
|
->placeholder('AUTOCRM_001')
|
|
->visible(fn (Get $get) => $get('paynet_enabled')),
|
|
Forms\Components\TextInput::make('paynet_service_id')
|
|
->label('Service ID')
|
|
->numeric()
|
|
->placeholder('12345')
|
|
->visible(fn (Get $get) => $get('paynet_enabled')),
|
|
Forms\Components\TextInput::make('paynet_user')
|
|
->label('User API')
|
|
->visible(fn (Get $get) => $get('paynet_enabled')),
|
|
Forms\Components\TextInput::make('paynet_password')
|
|
->label('Parolă API')->password()->revealable()
|
|
->visible(fn (Get $get) => $get('paynet_enabled')),
|
|
Forms\Components\TextInput::make('paynet_secret')
|
|
->label('Secret semnătură')->password()->revealable()
|
|
->columnSpanFull()
|
|
->helperText('Cheia HMAC pentru semnarea cererilor + verificarea webhook-urilor de la Paynet.')
|
|
->visible(fn (Get $get) => $get('paynet_enabled')),
|
|
]),
|
|
Schemas\Components\Section::make('🏦 Transfer bancar (manual)')
|
|
->description('Datele apar pe facturi și pe pagina de plată a tenant-ului. Confirmarea o faci manual.')
|
|
->columns(2)
|
|
->collapsible()
|
|
->schema([
|
|
Forms\Components\Toggle::make('bank_enabled')->label('Activează plata prin transfer')->default(true)->live(),
|
|
Forms\Components\TextInput::make('bank_beneficiary')
|
|
->label('Beneficiar')->placeholder('AutoCRM SRL')
|
|
->visible(fn (Get $get) => $get('bank_enabled')),
|
|
Forms\Components\TextInput::make('bank_iban')
|
|
->label('IBAN')->placeholder('MD00 AG00 0000 ...')
|
|
->visible(fn (Get $get) => $get('bank_enabled')),
|
|
Forms\Components\TextInput::make('bank_bic')
|
|
->label('BIC / SWIFT')->placeholder('AGRNMD2X')
|
|
->visible(fn (Get $get) => $get('bank_enabled')),
|
|
Forms\Components\TextInput::make('bank_name')
|
|
->label('Banca')->placeholder('Moldova-Agroindbank')
|
|
->visible(fn (Get $get) => $get('bank_enabled')),
|
|
Forms\Components\Textarea::make('bank_instructions')
|
|
->label('Instrucțiuni adiționale')->rows(2)->columnSpanFull()
|
|
->visible(fn (Get $get) => $get('bank_enabled')),
|
|
]),
|
|
])
|
|
->statePath('data');
|
|
}
|
|
|
|
public function save(): void
|
|
{
|
|
$data = $this->form->getState();
|
|
|
|
PlatformSetting::put('payments.platform_currency', $data['platform_currency']);
|
|
PlatformSetting::put('payments.invoice_prefix', $data['invoice_prefix']);
|
|
PlatformSetting::put('payments.terms', $data['terms']);
|
|
|
|
PlatformSetting::put('payments.company_legal', [
|
|
'name' => $data['legal_name'] ?? null,
|
|
'idno' => $data['legal_idno'] ?? null,
|
|
'address' => $data['legal_address'] ?? null,
|
|
'phone' => $data['legal_phone'] ?? null,
|
|
'email' => $data['legal_email'] ?? null,
|
|
]);
|
|
|
|
PlatformSetting::put('payments.stripe', [
|
|
'enabled' => (bool) ($data['stripe_enabled'] ?? false),
|
|
'mode' => $data['stripe_mode'] ?? 'test',
|
|
'publishable_key' => $data['stripe_publishable'] ?? null,
|
|
'secret_key' => $data['stripe_secret'] ?? null,
|
|
'webhook_secret' => $data['stripe_webhook'] ?? null,
|
|
]);
|
|
|
|
PlatformSetting::put('payments.paypal', [
|
|
'enabled' => (bool) ($data['paypal_enabled'] ?? false),
|
|
'mode' => $data['paypal_mode'] ?? 'sandbox',
|
|
'client_id' => $data['paypal_client_id'] ?? null,
|
|
'secret' => $data['paypal_secret'] ?? null,
|
|
]);
|
|
|
|
PlatformSetting::put('payments.paynet', [
|
|
'enabled' => (bool) ($data['paynet_enabled'] ?? false),
|
|
'mode' => $data['paynet_mode'] ?? 'test',
|
|
'merchant_code' => $data['paynet_merchant_code'] ?? null,
|
|
'service_id' => $data['paynet_service_id'] ?? null,
|
|
'user' => $data['paynet_user'] ?? null,
|
|
'password' => $data['paynet_password'] ?? null,
|
|
'secret' => $data['paynet_secret'] ?? null,
|
|
]);
|
|
|
|
PlatformSetting::put('payments.bank', [
|
|
'enabled' => (bool) ($data['bank_enabled'] ?? false),
|
|
'beneficiary' => $data['bank_beneficiary'] ?? null,
|
|
'iban' => $data['bank_iban'] ?? null,
|
|
'bic' => $data['bank_bic'] ?? null,
|
|
'bank_name' => $data['bank_name'] ?? null,
|
|
'instructions' => $data['bank_instructions'] ?? null,
|
|
]);
|
|
|
|
Notification::make()->title('Setări plăți salvate')->success()->send();
|
|
}
|
|
|
|
protected function getFormActions(): array
|
|
{
|
|
return [
|
|
\Filament\Actions\Action::make('save')
|
|
->label('Salvează')
|
|
->submit('save'),
|
|
];
|
|
}
|
|
}
|