webmoney/backend/app/Console/Commands/SetupPayPalPlans.php
marco 54cccdd095 refactor: migração para desenvolvimento direto no servidor
- Removido README.md padrão do Laravel (backend)
- Removidos scripts de deploy (não mais necessários)
- Atualizado copilot-instructions.md para novo fluxo
- Adicionada documentação de auditoria do servidor
- Sincronizado código de produção com repositório

Novo workflow:
- Trabalhamos diretamente em /root/webmoney (symlink para /var/www/webmoney)
- Mudanças PHP são instantâneas
- Mudanças React requerem 'npm run build'
- Commit após validação funcional
2025-12-19 11:45:32 +01:00

190 lines
6.4 KiB
PHP
Executable File

<?php
namespace App\Console\Commands;
use App\Models\Plan;
use App\Services\PayPalService;
use Illuminate\Console\Command;
class SetupPayPalPlans extends Command
{
protected $signature = 'paypal:setup-plans';
protected $description = 'Create products and billing plans in PayPal for all active plans';
public function handle()
{
$this->info('🚀 Starting PayPal Plans Setup...');
$this->newLine();
$paypal = new PayPalService();
// Test authentication first
$this->info('Testing PayPal authentication...');
try {
$token = $paypal->getAccessToken();
$this->info('✅ PayPal authentication successful!');
$this->newLine();
} catch (\Exception $e) {
$this->error('❌ PayPal authentication failed: ' . $e->getMessage());
return 1;
}
// Get plans that don't have PayPal plan IDs yet
$plans = Plan::where('is_active', true)
->where('is_free', false)
->get();
if ($plans->isEmpty()) {
$this->warn('No paid plans found in database.');
return 0;
}
$this->info("Found {$plans->count()} paid plan(s) to setup in PayPal:");
$this->newLine();
foreach ($plans as $plan) {
$this->info("📦 Processing: {$plan->name}");
// Check if already has PayPal plan ID
if ($plan->paypal_plan_id) {
$this->warn(" Already has PayPal Plan ID: {$plan->paypal_plan_id}");
$this->line(" Skipping...");
$this->newLine();
continue;
}
try {
// Step 1: Create Product in PayPal
$this->line(" Creating product in PayPal...");
$product = $this->createProduct($paypal, $plan);
$this->info(" ✅ Product created: {$product['id']}");
// Step 2: Create Billing Plan in PayPal
$this->line(" Creating billing plan in PayPal...");
$billingPlan = $this->createBillingPlan($paypal, $plan, $product['id']);
$this->info(" ✅ Billing Plan created: {$billingPlan['id']}");
// Step 3: Save PayPal Plan ID to database
$plan->paypal_plan_id = $billingPlan['id'];
$plan->save();
$this->info(" ✅ Saved to database!");
$this->newLine();
} catch (\Exception $e) {
$this->error(" ❌ Error: " . $e->getMessage());
$this->newLine();
}
}
$this->info('🎉 PayPal Plans Setup completed!');
$this->newLine();
// Show summary
$this->table(
['Plan', 'Price', 'Billing', 'PayPal Plan ID'],
Plan::where('is_free', false)->get()->map(function ($p) {
return [
$p->name,
'€' . number_format($p->price, 2),
$p->billing_period,
$p->paypal_plan_id ?? 'Not set'
];
})
);
return 0;
}
private function createProduct(PayPalService $paypal, Plan $plan): array
{
$baseUrl = config('services.paypal.mode') === 'sandbox'
? 'https://api-m.sandbox.paypal.com'
: 'https://api-m.paypal.com';
// Get fresh token for this request
\Illuminate\Support\Facades\Cache::forget('paypal_access_token');
$token = $paypal->getAccessToken();
$response = \Illuminate\Support\Facades\Http::withToken($token)
->post("{$baseUrl}/v1/catalogs/products", [
'name' => "WEBMoney - {$plan->name}",
'description' => $plan->description ?? "Subscription plan for WEBMoney",
'type' => 'SERVICE',
'category' => 'SOFTWARE',
'home_url' => config('app.url'),
]);
if (!$response->successful()) {
throw new \Exception('Failed to create product: ' . $response->body());
}
return $response->json();
}
private function createBillingPlan(PayPalService $paypal, Plan $plan, string $productId): array
{
$baseUrl = config('services.paypal.mode') === 'sandbox'
? 'https://api-m.sandbox.paypal.com'
: 'https://api-m.paypal.com';
$billingCycles = [];
// Add trial period if plan has trial
if ($plan->trial_days > 0) {
$billingCycles[] = [
'frequency' => [
'interval_unit' => 'DAY',
'interval_count' => $plan->trial_days,
],
'tenure_type' => 'TRIAL',
'sequence' => 1,
'total_cycles' => 1,
'pricing_scheme' => [
'fixed_price' => [
'value' => '0',
'currency_code' => $plan->currency,
],
],
];
}
// Regular billing cycle
$billingCycles[] = [
'frequency' => [
'interval_unit' => $plan->billing_period === 'annual' ? 'YEAR' : 'MONTH',
'interval_count' => 1,
],
'tenure_type' => 'REGULAR',
'sequence' => $plan->trial_days > 0 ? 2 : 1,
'total_cycles' => 0, // Infinite
'pricing_scheme' => [
'fixed_price' => [
'value' => number_format($plan->price, 2, '.', ''),
'currency_code' => $plan->currency,
],
],
];
$response = \Illuminate\Support\Facades\Http::withToken($paypal->getAccessToken())
->post("{$baseUrl}/v1/billing/plans", [
'product_id' => $productId,
'name' => $plan->name,
'description' => $plan->description ?? "WEBMoney {$plan->name} subscription",
'status' => 'ACTIVE',
'billing_cycles' => $billingCycles,
'payment_preferences' => [
'auto_bill_outstanding' => true,
'setup_fee_failure_action' => 'CONTINUE',
'payment_failure_threshold' => 3,
],
]);
if (!$response->successful()) {
throw new \Exception('Failed to create billing plan: ' . $response->body());
}
return $response->json();
}
}