Add Parcel2Go account consent with PKCE
Deploy HickLab3D Dashboard / Deploy to production (push) Successful in 26s

This commit is contained in:
Hickmeister
2026-10-11 17:27:07 +01:00
parent 1c80811713
commit 1be66f099c
9 changed files with 321 additions and 9 deletions
@@ -7,13 +7,14 @@ use App\Models\EtsyConnection;
use App\Models\IntegrationSetting;
use App\Services\Etsy;
use App\Services\IntegrationSettings;
use App\Services\Parcel2Go;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class EtsySettingsController extends Controller
{
public function index(Request $request, Etsy $etsy, IntegrationSettings $settings): View
public function index(Request $request, Etsy $etsy, IntegrationSettings $settings, Parcel2Go $parcel2Go): View
{
abort_unless($request->user()->role === 'admin', 403);
@@ -37,6 +38,9 @@ class EtsySettingsController extends Controller
'base_url' => $parcel2go['base_url'] ?? '',
'scope' => $parcel2go['scope'] ?? 'public-api',
'collection_postcode' => $parcel2go['collection_postcode'] ?? '',
'profile_client_configured' => $parcel2Go->profileClientConfigured(),
'profile_connected' => $parcel2Go->profileConnected(),
'callback_url' => route('parcel2go.callback'),
],
'bambuddy' => [
'stored' => in_array('bambuddy', $storedIntegrations, true),
@@ -22,6 +22,7 @@ class IntegrationSettingsController extends Controller
'base_url' => ['nullable', 'url:https', 'max:2048'],
'scope' => ['nullable', 'string', 'in:public-api,public-api my-profile,public-api payment,public-api payment my-profile'],
'collection_postcode' => ['nullable', 'string', 'max:12'],
'profile_client_id' => ['nullable', 'string', 'max:255'],
],
default => [
'url' => ['nullable', 'url:https', 'max:2048'],
@@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers;
use App\Services\Parcel2Go;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Throwable;
class Parcel2GoConnectionController extends Controller
{
public function connect(Request $request, Parcel2Go $parcel2Go): RedirectResponse
{
abort_unless($request->user()->role === 'admin', 403);
if (! $parcel2Go->profileClientConfigured()) {
return redirect()->route('settings.index')->withErrors(['parcel2go' => 'Save the Parcel2Go Authorization Code Client ID first.']);
}
$state = bin2hex(random_bytes(24));
$verifier = rtrim(strtr(base64_encode(random_bytes(48)), '+/', '-_'), '=');
$request->session()->put('parcel2go_oauth', ['state' => $state, 'verifier' => $verifier, 'started' => time()]);
return redirect()->away($parcel2Go->authorizationUrl($state, $verifier));
}
public function callback(Request $request, Parcel2Go $parcel2Go): RedirectResponse
{
abort_unless($request->user()->role === 'admin', 403);
$pending = $request->session()->pull('parcel2go_oauth');
if (! is_array($pending) || time() - ($pending['started'] ?? 0) > 600
|| ! is_string($request->query('state'))
|| ! hash_equals($pending['state'] ?? '', $request->query('state'))
|| ! is_string($request->query('code'))) {
return redirect()->route('settings.index')->withErrors(['parcel2go' => 'Parcel2Go consent expired or was not verified. Please try again.']);
}
try {
$parcel2Go->connectProfile($request->query('code'), $pending['verifier']);
return redirect()->route('settings.index')->with('status', 'Parcel2Go account connected. Shipment history is available in Shipping.');
} catch (Throwable $exception) {
report($exception);
return redirect()->route('settings.index')->withErrors(['parcel2go' => 'Parcel2Go rejected the account connection. Check the Client ID, scopes and callback URL.']);
}
}
}
+6 -4
View File
@@ -42,11 +42,13 @@ class ShippingController extends Controller
$orders = $parcel2Go->fetch('me/orders/detail');
$historyAvailable = true;
} catch (Throwable $exception) {
$profileNotice = $exception instanceof RequestException && in_array($exception->response->status(), [401, 403], true)
? 'Parcel2Go denied shipment history for this client. Request my-profile access from Parcel2Go API support.'
: 'Parcel2Go shipment history is temporarily unavailable.';
$profileNotice = $parcel2Go->profileConnected()
? 'Parcel2Go account access needs attention. Reconnect the account in Settings.'
: ($exception instanceof RequestException && in_array($exception->response->status(), [401, 403], true)
? 'Parcel2Go denied shipment history for this client. Connect an Authorization Code client in Settings.'
: 'Parcel2Go shipment history is temporarily unavailable.');
}
if ($parcel2Go->hasScope('my-profile')) {
if ($parcel2Go->profileConnected() || $parcel2Go->hasScope('my-profile')) {
try {
$account = $parcel2Go->fetch('me/detail');
$balance = $parcel2Go->fetch('me/prepay/balance');