Update pricing UX, billing flows, and API rules
This commit is contained in:
@@ -2,7 +2,13 @@
|
||||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schedule;
|
||||
use App\Services\LiveSqlImportService;
|
||||
use App\Services\Billing\PaypalWebhookProcessor;
|
||||
use App\Services\Billing\PayPalPlanSyncService;
|
||||
use App\Models\WebhookEvent;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use App\Mail\TestMailketing;
|
||||
|
||||
Artisan::command('inspire', function () {
|
||||
$this->comment(Inspiring::quote());
|
||||
@@ -16,3 +22,80 @@ Artisan::command('dewemoji:import-live-sql {path : Absolute path to dewemojiAPI_
|
||||
$importer = app(LiveSqlImportService::class);
|
||||
$importer->import($path, $truncate, $batch, $this->output);
|
||||
})->purpose('Import live SQL dump into the current database');
|
||||
|
||||
Artisan::command('dewemoji:webhooks:process {--limit=100 : Max events to process} {--status=pending,received : Comma-separated statuses}', function () {
|
||||
$limit = (int) $this->option('limit');
|
||||
$statuses = array_filter(array_map('trim', explode(',', (string) $this->option('status'))));
|
||||
|
||||
if (empty($statuses)) {
|
||||
$this->error('No statuses provided.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
$processor = app(PaypalWebhookProcessor::class);
|
||||
|
||||
$events = WebhookEvent::query()
|
||||
->whereIn('status', $statuses)
|
||||
->orderBy('id')
|
||||
->limit($limit)
|
||||
->get();
|
||||
|
||||
$processed = 0;
|
||||
$failed = 0;
|
||||
|
||||
foreach ($events as $event) {
|
||||
try {
|
||||
if ($event->provider === 'paypal') {
|
||||
$processor->process((string) ($event->event_type ?? ''), $event->payload ?? []);
|
||||
}
|
||||
$event->update([
|
||||
'status' => 'processed',
|
||||
'processed_at' => now(),
|
||||
'error' => null,
|
||||
]);
|
||||
$processed++;
|
||||
} catch (\Throwable $e) {
|
||||
$event->update([
|
||||
'status' => 'error',
|
||||
'processed_at' => now(),
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info("Processed {$processed} events, failed {$failed}.");
|
||||
return 0;
|
||||
})->purpose('Process pending webhook events');
|
||||
|
||||
Schedule::command('dewemoji:webhooks:process --limit=200')->everyMinute()->withoutOverlapping();
|
||||
|
||||
Artisan::command('paypal:sync-plans {--mode=both : sandbox|live|both}', function () {
|
||||
$mode = (string) $this->option('mode');
|
||||
$service = app(PayPalPlanSyncService::class);
|
||||
|
||||
$runMode = match ($mode) {
|
||||
'sandbox' => ['sandbox'],
|
||||
'live' => ['live'],
|
||||
default => ['sandbox', 'live'],
|
||||
};
|
||||
|
||||
foreach ($runMode as $env) {
|
||||
$this->info("Syncing PayPal plans: {$env}");
|
||||
$result = $service->sync($env);
|
||||
$this->line("Created: {$result['created']} · Updated: {$result['updated']} · Deactivated: {$result['deactivated']} · Skipped: {$result['skipped']}");
|
||||
}
|
||||
})->purpose('Create/rotate PayPal plans based on pricing plans');
|
||||
|
||||
Artisan::command('mailketing:test {email : Recipient email address}', function () {
|
||||
$email = (string) $this->argument('email');
|
||||
|
||||
try {
|
||||
Mail::to($email)->send(new TestMailketing());
|
||||
$this->info("Mailketing test email sent to {$email}.");
|
||||
return 0;
|
||||
} catch (\Throwable $e) {
|
||||
$this->error('Mailketing test failed: '.$e->getMessage());
|
||||
return 1;
|
||||
}
|
||||
})->purpose('Send a Mailketing API test email');
|
||||
|
||||
Reference in New Issue
Block a user