diff --git a/.env.example b/.env.example index 8222755..07e08d4 100644 --- a/.env.example +++ b/.env.example @@ -39,3 +39,7 @@ OIDC_CLIENT_ID= OIDC_CLIENT_SECRET= OIDC_REDIRECT_URI="${APP_URL}/auth/social/oidc/callback" +NORTH_CHECKOUT_ID= +NORTH_PROFILE_ID= +NORTH_PRIVATE_API_KEY= + diff --git a/app/Http/Controllers/NorthCheckoutController.php b/app/Http/Controllers/NorthCheckoutController.php new file mode 100644 index 0000000..71e83a1 --- /dev/null +++ b/app/Http/Controllers/NorthCheckoutController.php @@ -0,0 +1,212 @@ +firstOrFail(); + + // Check if already checked out + if (Checkout::where('bidder_num', $bidder->idbidders)->exists()) { + return redirect('/mywinnings?bidder_number=' . $bidder->bidder_assigned_number)->with('error', 'Bidder has already checked out.'); + } + + $winnings = WinningBids::where('winning_bidder_num', $bidder->idbidders)->get(); + $total_cost = $winnings->sum('winning_cost'); + + if ($total_cost <= 0) { + return redirect('/mywinnings?bidder_number=' . $bidder->bidder_assigned_number)->with('error', 'No winnings found for this bidder.'); + } + + return view('north_checkout', [ + 'bidder' => $bidder, + 'total_cost' => $total_cost, + ]); + } + + public function createSession(Request $request, $bidder_id) + { + $bidder = Bidders::findOrFail($bidder_id); + $winnings = WinningBids::with('items')->where('winning_bidder_num', $bidder->idbidders)->get(); + $total_cost = $winnings->sum('winning_cost'); + + $products = $winnings->map(function($winning) { + return [ + 'name' => $winning->items->item_desc ?? 'Auction Item', + 'price' => (float)$winning->winning_cost, + 'quantity' => 1 + ]; + })->toArray(); + + $apiKey = config('services.north.private_api_key'); + $checkoutId = config('services.north.checkout_id'); + $profileId = config('services.north.profile_id'); + + if (!$apiKey || !$checkoutId || !$profileId) { + return response()->json(['error' => 'North configuration missing.'], 500); + } + + $response = Http::withHeaders([ + 'Authorization' => 'Bearer ' . $apiKey, + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ])->post('https://checkout.north.com/api/sessions', [ + 'checkoutId' => $checkoutId, + 'profileId' => $profileId, + 'amount' => (float)$total_cost, + 'products' => $products, + ]); + + if ($response->failed()) { + Log::error('North Session Creation Failed: ' . $response->status() . ' ' . $response->body()); + return response()->json([ + 'error' => 'Failed to create checkout session: ' . ($response->json('message') ?? 'Unknown error'), + 'status' => $response->status(), + 'body' => $response->body() + ], 500); + } + + $data = $response->json(); + + // If json() is null but body is not empty, it might be a parsing error + if (is_null($data) && !empty($response->body())) { + Log::error('North Session Response is not JSON: ' . $response->body()); + return response()->json([ + 'error' => 'Response from North is not valid JSON.', + 'raw_body' => $response->body() + ], 500); + } + + $token = $data['token'] ?? + $data['sessionToken'] ?? + $data['id'] ?? + $data['session_id'] ?? + ($data['session']['id'] ?? null); + + if (!$token) { + Log::error('North Session Token Missing in Response: ' . json_encode($data)); + return response()->json([ + 'error' => 'Session token not found in API response.', + 'debug_response' => $data, + 'raw_body' => $response->body() + ], 500); + } + + return response()->json(['sessionToken' => $token]); + } + + public function verify(Request $request, $bidder_id) + { + $bidder = Bidders::findOrFail($bidder_id); + $sessionToken = $request->query('sessionToken'); + if (!$sessionToken) { + return redirect('/mywinnings?bidder_number=' . $bidder->bidder_assigned_number)->with('error', 'Missing session token.'); + } + + $apiKey = config('services.north.private_api_key'); + $checkoutId = config('services.north.checkout_id'); + $profileId = config('services.north.profile_id'); + + $response = Http::withHeaders([ + 'Authorization' => 'Bearer ' . $apiKey, + 'SessionToken' => $sessionToken, + 'CheckoutId' => $checkoutId, + 'ProfileId' => $profileId, + 'Accept' => 'application/json', + ])->get('https://checkout.north.com/api/sessions/status'); + + if ($response->failed()) { + Log::error('North Session Verification Failed: ' . $response->status() . ' ' . $response->body()); + return redirect('/mywinnings?bidder_number=' . $bidder->bidder_assigned_number)->with('error', 'Failed to verify payment status. Status: ' . $response->status()); + } + + $status = $response->json(); + $currentStatus = $status['status'] ?? ''; + + // The North API status check might return Approved, completed, success, authorized, or captured. + $successStatuses = ['approved', 'completed', 'success', 'authorized', 'captured']; + + if (in_array(strtolower($currentStatus), $successStatuses)) { + // Check if already checked out to avoid duplicates + $existingCheckout = Checkout::where('bidder_num', $bidder->idbidders)->first(); + + if (!$existingCheckout) { + // According to docs, when status is Approved, transaction details are in 'body' + // Digital wallets might have these at the top level + $body = $status['body'] ?? []; + $winnertotal = $status['amount'] ?? + ($body['amount'] ?? + ($status['amount_total'] ?? + WinningBids::where('winning_bidder_num', $bidder->idbidders)->sum('winning_cost'))); + + $payment_method = 3; // Credit Card + $cc_transaction = $body['auth_guid'] ?? + ($status['transaction_id'] ?? + ($status['transactionId'] ?? + ($status['id'] ?? 'NORTH_EC'))); + + $cc_amount = $winnertotal; + $check_number = null; + + $checkout_id = DB::table('checkout')->insertGetID( + [ + 'bidder_num' => $bidder->idbidders, + 'winnertotal' => $winnertotal, + 'payment_method' => $payment_method, + 'check_number' => $check_number, + 'cc_transaction' => $cc_transaction, + 'cc_amount' => $cc_amount, + 'created_at' => now(), + 'updated_at' => now(), + ] + ); + } else { + $checkout_id = $existingCheckout->checkout_id; + $payment_method = $existingCheckout->payment_method; + $cc_transaction = $existingCheckout->cc_transaction; + $check_number = $existingCheckout->check_number; + } + + // Replicate the data for checkout_complete view + $checkout_list_results = DB::select("SELECT + *, items.item_assigned_num, items.item_desc + FROM winning_bids + INNER JOIN items AS items + ON winning_bids.winning_item_num=items.iditems + WHERE winning_bidder_num = $bidder->idbidders + "); + + $checkout_info_results = DB::select("SELECT + winning_bids.*, + bidders.*, + sum(winning_cost) AS total_cost + FROM winning_bids + INNER JOIN bidders AS bidders + ON winning_bids.winning_bidder_num=bidders.idbidders + WHERE winning_bidder_num = $bidder->idbidders + GROUP BY winning_bids.winning_bidder_num + "); + + return view('checkout_complete', [ + 'checkout_result' => $checkout_id, + 'checkout_list_results' => $checkout_list_results, + 'checkout_info_results' => $checkout_info_results, + 'payment_method' => $payment_method, + 'check_number' => $check_number, + 'cc_transaction' => $cc_transaction + ]); + } + + return redirect('/mywinnings?bidder_number=' . $bidder->bidder_assigned_number)->with('error', 'Payment not completed. Status: ' . ($status['status'] ?? 'unknown')); + } +} diff --git a/app/Http/Controllers/PagesController.php b/app/Http/Controllers/PagesController.php index 5078e37..588a913 100644 --- a/app/Http/Controllers/PagesController.php +++ b/app/Http/Controllers/PagesController.php @@ -6,7 +6,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use View; use App\helpers; -use PDF; +use Spatie\LaravelPdf\Facades\Pdf; use App\Models\Bidders; use App\Models\Items; use App\Models\Checkout; @@ -19,7 +19,7 @@ use App\Models\CarShowCategory; use App\Models\Types; use App\Models\Vehicles; use App\Models\VehicleScores; - +use Dompdf\Dompdf; class PagesController extends Controller { public function home() @@ -250,6 +250,49 @@ class PagesController extends Controller return view('receiptpdf', $checkout_data); } + public function downloadReceiptPdf(Request $request) + { + $checkoutid = $request->checkout_id; + $checkout_final_results = Checkout::where('checkout_id', '=', $checkoutid)->first(); + if (!$checkout_final_results) { + return redirect('/mywinnings')->with('error', 'Checkout record not found.'); + } + + $bidder_num = $checkout_final_results->bidder_num; + $checkout_list_results = DB::select("SELECT + *, items.item_assigned_num, items.item_desc + FROM winning_bids + INNER JOIN items AS items ON winning_bids.winning_item_num=items.iditems + WHERE winning_bidder_num = $bidder_num + "); + $checkout_info_results = DB::select("SELECT + winning_bids.*, + bidders.*, + sum(winning_cost) AS total_cost + FROM winning_bids + INNER JOIN bidders AS bidders ON winning_bids.winning_bidder_num=bidders.idbidders + WHERE winning_bidder_num = $bidder_num + GROUP BY winning_bids.winning_bidder_num + "); + + $options = new \Dompdf\Options(); + $options->set('isHtml5ParserEnabled', true); + $options->set('isRemoteEnabled', true); + $dompdf = new Dompdf($options); + + $html = view('receiptpdf', [ + 'checkout_final_results' => $checkout_final_results, + 'checkout_list_results' => $checkout_list_results, + 'checkout_info_results' => $checkout_info_results + ])->render(); + + $dompdf->loadHtml($html); + $dompdf->setPaper('letter', 'portrait'); + $dompdf->render(); + + return $dompdf->stream('receipt-'.$checkoutid.'.pdf'); + } + public function reprintReceipt(Request $reprint_receipt_req) { if (!$reprint_receipt_req->reprintbiddernum) { @@ -535,10 +578,13 @@ class PagesController extends Controller $total_cost = $winnings->sum('winning_cost'); + $is_checked_out = \App\Models\Checkout::where('bidder_num', $bidder->idbidders)->exists(); + return view('mywinnings_results', [ 'bidder' => $bidder, 'winnings' => $winnings, - 'total_cost' => $total_cost + 'total_cost' => $total_cost, + 'is_checked_out' => $is_checked_out ]); } } diff --git a/composer.json b/composer.json index 7cf9e77..2754117 100644 --- a/composer.json +++ b/composer.json @@ -8,13 +8,15 @@ "php": "^8.2", "barryvdh/laravel-snappy": "^1.0", "carlos-meneses/laravel-mpdf": "^2.1", + "dompdf/dompdf": "^3.1", "filament/filament": "^5.0", "kovah/laravel-socialite-oidc": "^0.7.0", "laravel/framework": "^11.0", "laravel/socialite": "^5.26", "laravel/tinker": "^2.9", "laravel/ui": "^4.2", - "socialiteproviders/manager": "^4.9" + "socialiteproviders/manager": "^4.9", + "spatie/laravel-pdf": "^2.8" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.8", diff --git a/composer.lock b/composer.lock index 6de3d70..5efc729 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3c08b43425d232f81481839d3c2286fc", + "content-hash": "bc73ddd14c4ed8e50e635ca2db38cdd8", "packages": [ { "name": "barryvdh/laravel-snappy", @@ -928,6 +928,161 @@ ], "time": "2024-02-05T11:56:58+00:00" }, + { + "name": "dompdf/dompdf", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", + "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", + "shasum": "" + }, + "require": { + "dompdf/php-font-lib": "^1.0.0", + "dompdf/php-svg-lib": "^1.0.0", + "ext-dom": "*", + "ext-mbstring": "*", + "masterminds/html5": "^2.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-gd": "*", + "ext-json": "*", + "ext-zip": "*", + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance", + "ext-zlib": "Needed for pdf stream compression" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "The Dompdf Community", + "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/v3.1.5" + }, + "time": "2026-03-03T13:54:37+00:00" + }, + { + "name": "dompdf/php-font-lib", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a6e9a688a2a80016ac080b97be73d3e10c444c9a", + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "The FontLib Community", + "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/dompdf/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.2" + }, + "time": "2026-01-20T14:10:26+00:00" + }, + { + "name": "dompdf/php-svg-lib", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8259ffb930817e72b1ff1caef5d226501f3dfeb1", + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4 || ^9.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The SvgLib Community", + "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/dompdf/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.2" + }, + "time": "2026-01-02T16:01:13+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.6.0", @@ -3774,6 +3929,73 @@ ], "time": "2026-04-02T20:48:35+00:00" }, + { + "name": "masterminds/html5", + "version": "2.10.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "fcf91eb64359852f00d921887b219479b4f21251" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", + "reference": "fcf91eb64359852f00d921887b219479b4f21251", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" + }, + "time": "2025-07-25T09:04:22+00:00" + }, { "name": "monolog/monolog", "version": "3.10.0", @@ -5876,6 +6098,86 @@ ], "time": "2026-03-19T10:36:26+00:00" }, + { + "name": "sabberworm/php-css-parser", + "version": "v9.3.0", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", + "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "thecodingmachine/safe": "^1.3 || ^2.5 || ^3.4" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/extension-installer": "1.4.3", + "phpstan/phpstan": "1.12.32 || 2.1.32", + "phpstan/phpstan-phpunit": "1.4.2 || 2.0.8", + "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.7", + "phpunit/phpunit": "8.5.52", + "rawr/phpunit-data-provider": "3.3.1", + "rector/rector": "1.2.10 || 2.2.8", + "rector/type-perfect": "1.0.0 || 2.1.0", + "squizlabs/php_codesniffer": "4.0.1", + "thecodingmachine/phpstan-safe-rule": "1.2.0 || 1.4.1" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.4.x-dev" + } + }, + "autoload": { + "files": [ + "src/Rule/Rule.php", + "src/RuleSet/RuleContainer.php" + ], + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.3.0" + }, + "time": "2026-03-03T17:31:43+00:00" + }, { "name": "scrivo/highlight.php", "version": "v9.18.1.10", @@ -6220,6 +6522,99 @@ ], "time": "2026-02-21T12:49:54+00:00" }, + { + "name": "spatie/laravel-pdf", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-pdf.git", + "reference": "2ba286a03ee5e22463fb0a6e706b157a21d5f60a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-pdf/zipball/2ba286a03ee5e22463fb0a6e706b157a21d5f60a", + "reference": "2ba286a03ee5e22463fb0a6e706b157a21d5f60a", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^11.0|^12.0|^13.0", + "php": "^8.2", + "spatie/laravel-package-tools": "^1.16.1", + "spatie/temporary-directory": "^2.2.1" + }, + "require-dev": { + "chrome-php/chrome": "^1.0", + "dompdf/dompdf": "^3.0", + "ext-imagick": "*", + "larastan/larastan": "^2.7.0|^3.0", + "laravel/pint": "^1.13.7", + "nunomaduro/collision": "^8.0", + "orchestra/testbench": "^9.6|^10.0|^11.0", + "pestphp/pest": "^2.30|^3.7|^4.4", + "pestphp/pest-plugin-arch": "^2.5|^3.0|^4.0", + "pestphp/pest-plugin-laravel": "^2.2|^3.1|^4.1", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan-deprecation-rules": "^1.1.4|^2.0", + "phpstan/phpstan-phpunit": "^1.3.15|^2.0", + "pontedilana/php-weasyprint": "^2.4", + "spatie/image": "^3.3.2", + "spatie/invade": "^2.1", + "spatie/laravel-ray": "^1.33", + "spatie/pdf-to-image": "^2.2|^3.1", + "spatie/pdf-to-text": "^1.52.1", + "spatie/pest-expectations": "^1.5", + "spatie/pest-plugin-snapshots": "^2.1", + "spatie/pixelmatch-php": "^1.0", + "wnx/sidecar-browsershot": "^2.0" + }, + "suggest": { + "chrome-php/chrome": "Required for the Chrome PHP driver (^1.0)", + "dompdf/dompdf": "Required for the DOMPDF driver (^3.0)", + "spatie/browsershot": "Required for the Browsershot driver (^4.0|^5.0)" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "LaravelPdf": "Pdf" + }, + "providers": [ + "Spatie\\LaravelPdf\\PdfServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Support/functions.php" + ], + "psr-4": { + "Spatie\\LaravelPdf\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Create PDFs in Laravel apps", + "homepage": "https://github.com/spatie/laravel-pdf", + "keywords": [ + "laravel", + "laravel-pdf", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-pdf/issues", + "source": "https://github.com/spatie/laravel-pdf/tree/2.8.0" + }, + "time": "2026-04-27T08:15:52+00:00" + }, { "name": "spatie/shiki-php", "version": "2.3.3", @@ -6285,6 +6680,67 @@ ], "time": "2026-02-01T09:30:04+00:00" }, + { + "name": "spatie/temporary-directory", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/temporary-directory.git", + "reference": "662e481d6ec07ef29fd05010433428851a42cd07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/662e481d6ec07ef29fd05010433428851a42cd07", + "reference": "662e481d6ec07ef29fd05010433428851a42cd07", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\TemporaryDirectory\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Vanderbist", + "email": "alex@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily create, use and destroy temporary directories", + "homepage": "https://github.com/spatie/temporary-directory", + "keywords": [ + "php", + "spatie", + "temporary-directory" + ], + "support": { + "issues": "https://github.com/spatie/temporary-directory/issues", + "source": "https://github.com/spatie/temporary-directory/tree/2.3.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2026-01-12T07:42:22+00:00" + }, { "name": "symfony/clock", "version": "v8.0.8", @@ -8769,6 +9225,149 @@ ], "time": "2026-03-30T13:44:50+00:00" }, + { + "name": "thecodingmachine/safe", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^10", + "squizlabs/php_codesniffer": "^3.2" + }, + "type": "library", + "autoload": { + "files": [ + "lib/special_cases.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rnp.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "classmap": [ + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "generated/Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/OskarStark", + "type": "github" + }, + { + "url": "https://github.com/shish", + "type": "github" + }, + { + "url": "https://github.com/silasjoisten", + "type": "github" + }, + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2026-02-04T18:08:13+00:00" + }, { "name": "tijsverkoyen/css-to-inline-styles", "version": "v2.4.0", diff --git a/config/services.php b/config/services.php index 0b3b30c..230389e 100644 --- a/config/services.php +++ b/config/services.php @@ -42,4 +42,10 @@ return [ 'redirect' => env('OIDC_REDIRECT_URI'), ], + 'north' => [ + 'checkout_id' => env('NORTH_CHECKOUT_ID'), + 'profile_id' => env('NORTH_PROFILE_ID'), + 'private_api_key' => env('NORTH_PRIVATE_API_KEY'), + ], + ]; diff --git a/resources/views/checkout_complete.blade.php b/resources/views/checkout_complete.blade.php index 6acf915..9c45645 100644 --- a/resources/views/checkout_complete.blade.php +++ b/resources/views/checkout_complete.blade.php @@ -14,21 +14,24 @@
No winning bids found for this bidder number.
@endif diff --git a/resources/views/north_checkout.blade.php b/resources/views/north_checkout.blade.php new file mode 100644 index 0000000..6a520d9 --- /dev/null +++ b/resources/views/north_checkout.blade.php @@ -0,0 +1,112 @@ +@extends('layouts.app') + +@section('content') +Loading secure checkout...
+