Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
NuvemshopOAuthController
0.00% covered (danger)
0.00%
0 / 54
0.00% covered (danger)
0.00%
0 / 3
72
0.00% covered (danger)
0.00%
0 / 1
 redirect
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 callback
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
30
 storeCredentials
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Http\Controllers\Admin;
4
5use App\Enums\IntegrationStatus;
6use App\Http\Controllers\Concerns\ResolvesContext;
7use App\Http\Controllers\Controller;
8use App\Models\IntegrationProvider;
9use App\Models\StoreIntegration;
10use App\Services\Nuvemshop\NuvemshopAuthService;
11use Illuminate\Http\RedirectResponse;
12use Illuminate\Http\Request;
13use Illuminate\Support\Str;
14
15class NuvemshopOAuthController extends Controller
16{
17    use ResolvesContext;
18
19    public function redirect(Request $request, NuvemshopAuthService $authService): RedirectResponse
20    {
21        $state = Str::random(40);
22
23        $request->session()->put('nuvemshop_oauth_state', $state);
24
25        try {
26            return redirect()->away($authService->authorizationUrl($state));
27        } catch (\RuntimeException $exception) {
28            return back()->withErrors([
29                'oauth' => $exception->getMessage(),
30            ]);
31        }
32    }
33
34    public function callback(Request $request, NuvemshopAuthService $authService): RedirectResponse
35    {
36        if ($request->query('state') !== $request->session()->pull('nuvemshop_oauth_state')) {
37            return redirect()
38                ->route('admin.integrations.index')
39                ->withErrors(['oauth' => 'State OAuth inválido.']);
40        }
41
42        $code = $request->query('code');
43
44        if (blank($code)) {
45            return redirect()
46                ->route('admin.integrations.index')
47                ->withErrors(['oauth' => 'Código OAuth não recebido.']);
48        }
49
50        if ((bool) config('services.nuvemshop.mock')) {
51            return $this->storeCredentials([
52                'access_token' => 'mock-oauth-token',
53                'scope' => 'read_orders write_coupons',
54                'user_id' => '123456',
55            ])->with('success', 'OAuth mock concluído.');
56        }
57
58        try {
59            $payload = $authService->exchangeAuthorizationCode((string) $code);
60
61            $authService->connectStore($this->currentStore(), $payload);
62        } catch (\RuntimeException $exception) {
63            return redirect()
64                ->route('admin.integrations.index')
65                ->withErrors(['oauth' => $exception->getMessage()]);
66        }
67
68        return redirect()
69            ->route('admin.integrations.index')
70            ->with('success', 'Integração Nuvemshop conectada.');
71    }
72
73    private function storeCredentials(array $payload): RedirectResponse
74    {
75        $store = $this->currentStore();
76
77        $provider = IntegrationProvider::where('slug', 'nuvemshop')->firstOrFail();
78
79        StoreIntegration::updateOrCreate(
80            [
81                'store_id' => $store->id,
82                'provider_id' => $provider->id,
83            ],
84            [
85                'tenant_id' => $store->tenant_id,
86                'external_store_id' => (string) data_get($payload, 'user_id', data_get($payload, 'store_id')),
87                'access_token' => data_get($payload, 'access_token'),
88                'refresh_token' => data_get($payload, 'refresh_token'),
89                'scopes' => app(NuvemshopAuthService::class)->parseScopes(data_get($payload, 'scope', '')),
90                'status' => IntegrationStatus::Connected->value,
91                'installed_at' => now(),
92                'metadata' => [
93                    'oauth_response' => collect($payload)
94                        ->except(['access_token', 'refresh_token'])
95                        ->toArray(),
96                ],
97            ]
98        );
99
100        return redirect()->route('admin.integrations.index');
101    }
102}