@fleetbase/storefront-engine 0.3.26 → 0.3.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/composer.json
CHANGED
package/extension.json
CHANGED
package/package.json
CHANGED
|
@@ -19,6 +19,7 @@ use Fleetbase\Storefront\Http\Requests\InitializeCheckoutRequest;
|
|
|
19
19
|
use Fleetbase\Storefront\Models\Cart;
|
|
20
20
|
use Fleetbase\Storefront\Models\Checkout;
|
|
21
21
|
use Fleetbase\Storefront\Models\Customer;
|
|
22
|
+
use Fleetbase\Storefront\Models\FoodTruck;
|
|
22
23
|
use Fleetbase\Storefront\Models\Gateway;
|
|
23
24
|
use Fleetbase\Storefront\Models\Product;
|
|
24
25
|
use Fleetbase\Storefront\Models\Store;
|
|
@@ -475,8 +476,8 @@ class CheckoutController extends Controller
|
|
|
475
476
|
$invoiceAmount = $amount;
|
|
476
477
|
$invoiceCode = $gateway->sandbox ? 'TEST_INVOICE' : $gateway->config->invoice_id;
|
|
477
478
|
$invoiceDescription = $about->name . ' cart checkout';
|
|
478
|
-
$invoiceReceiverCode = $
|
|
479
|
-
$senderInvoiceNo = $
|
|
479
|
+
$invoiceReceiverCode = $checkout->public_id;
|
|
480
|
+
$senderInvoiceNo = $checkout->public_id;
|
|
480
481
|
|
|
481
482
|
// Create qpay invoice
|
|
482
483
|
$invoice = $qpay->createSimpleInvoice($invoiceAmount, $invoiceCode, $invoiceDescription, $invoiceReceiverCode, $senderInvoiceNo, $callbackUrl);
|
|
@@ -491,69 +492,137 @@ class CheckoutController extends Controller
|
|
|
491
492
|
]);
|
|
492
493
|
}
|
|
493
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Capture and process QPay callback.
|
|
497
|
+
*
|
|
498
|
+
* This controller method handles QPay callback requests by verifying and processing
|
|
499
|
+
* payment information for a specified checkout. It performs the following steps:
|
|
500
|
+
*
|
|
501
|
+
* - Retrieves the checkout identifier from the request.
|
|
502
|
+
* - Looks up the associated Checkout and Gateway records.
|
|
503
|
+
* - If in sandbox mode and a test scenario is provided, it simulates a test payment
|
|
504
|
+
* response for either success or error scenarios.
|
|
505
|
+
* - Initializes a QPay instance with the gateway configuration and sets the authentication token.
|
|
506
|
+
* - Retrieves the invoice ID from the checkout options and performs a payment check using QPay's API.
|
|
507
|
+
* - Publishes the payment data or error response to the SocketCluster channel.
|
|
508
|
+
*
|
|
509
|
+
* Depending on the 'respond' flag from the request, the method returns a JSON response
|
|
510
|
+
* or completes the processing without returning data.
|
|
511
|
+
*
|
|
512
|
+
* @param Request $request The HTTP request containing:
|
|
513
|
+
* - `checkout` (string): The public checkout identifier.
|
|
514
|
+
* - `respond` (boolean): Whether to return a JSON response.
|
|
515
|
+
* - `test` (string|null): A test scenario indicator ('success' or 'error') for sandbox mode.
|
|
516
|
+
*
|
|
517
|
+
* @return \Illuminate\Http\JsonResponse a JSON response with payment data or error details
|
|
518
|
+
*
|
|
519
|
+
* @throws \Exception if an error occurs during payment processing, an API error is returned
|
|
520
|
+
*/
|
|
494
521
|
public function captureQPayCallback(Request $request)
|
|
495
522
|
{
|
|
496
|
-
$checkoutId
|
|
497
|
-
$
|
|
498
|
-
$
|
|
499
|
-
|
|
500
|
-
if (
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
$data = ['payment' =>(array) $payment, 'checkout' => $checkout->public_id, 'error' => null];
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
SocketClusterService::publish('checkout.' . $checkout->public_id, $data);
|
|
546
|
-
if ($respond) {
|
|
547
|
-
return response()->json($data);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
} catch (\Exception $e) {
|
|
551
|
-
Log::error('[QPAY CHECKOUT ERROR: ' . $e->getMessage() . ']', $checkout->toArray());
|
|
552
|
-
if ($respond) {
|
|
553
|
-
return response()->apiError($e->getMessage());
|
|
554
|
-
}
|
|
555
|
-
}
|
|
523
|
+
$checkoutId = $request->input('checkout');
|
|
524
|
+
$shouldRespond = $request->boolean('respond');
|
|
525
|
+
$testScenario = $request->input('test'); // Expected: 'success' or 'error'
|
|
526
|
+
|
|
527
|
+
if (!$checkoutId) {
|
|
528
|
+
return response()->json([
|
|
529
|
+
'error' => 'CHECKOUT_ID_MISSING',
|
|
530
|
+
'checkout' => null,
|
|
531
|
+
'payment' => null,
|
|
532
|
+
]);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
$checkout = Checkout::where('public_id', $checkoutId)->first();
|
|
536
|
+
if (!$checkout) {
|
|
537
|
+
return response()->json([
|
|
538
|
+
'error' => 'CHECKOUT_SESSION_NOT_FOUND',
|
|
539
|
+
'checkout' => null,
|
|
540
|
+
'payment' => null,
|
|
541
|
+
]);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
$gateway = Gateway::where('uuid', $checkout->gateway_uuid)->first();
|
|
545
|
+
if (!$gateway) {
|
|
546
|
+
return response()->json([
|
|
547
|
+
'error' => 'GATEWAY_NOT_CONFIGURED',
|
|
548
|
+
'checkout' => $checkout->public_id,
|
|
549
|
+
'payment' => null,
|
|
550
|
+
]);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
try {
|
|
554
|
+
// Handle test scenarios if in sandbox mode.
|
|
555
|
+
if ($gateway->sandbox && in_array($testScenario, ['success', 'error'], true)) {
|
|
556
|
+
$data = [
|
|
557
|
+
'checkout' => $checkout->public_id,
|
|
558
|
+
'payment' => null,
|
|
559
|
+
'error' => null,
|
|
560
|
+
];
|
|
561
|
+
|
|
562
|
+
if ($testScenario === 'success') {
|
|
563
|
+
$data['payment'] = QPay::createTestPaymentDataFromCheckout($checkout);
|
|
564
|
+
} else {
|
|
565
|
+
$data['error'] = [
|
|
566
|
+
'error' => 'PAYMENT_NOT_PAID',
|
|
567
|
+
'message' => 'Payment has not been paid!',
|
|
568
|
+
];
|
|
556
569
|
}
|
|
570
|
+
|
|
571
|
+
SocketClusterService::publish('checkout.' . $checkout->public_id, $data);
|
|
572
|
+
|
|
573
|
+
return $shouldRespond ? response()->json($data) : response()->json();
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// Create the QPay instance.
|
|
577
|
+
$qpay = QPay::instance(
|
|
578
|
+
$gateway->config->username,
|
|
579
|
+
$gateway->config->password,
|
|
580
|
+
$gateway->callback_url
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
if ($gateway->sandbox) {
|
|
584
|
+
$qpay->useSandbox();
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
$qpay->setAuthToken();
|
|
588
|
+
|
|
589
|
+
$invoiceId = $checkout->getOption('qpay_invoice_id');
|
|
590
|
+
if (!$invoiceId) {
|
|
591
|
+
Log::error("Missing QPay invoice ID for checkout: {$checkout->public_id}");
|
|
592
|
+
|
|
593
|
+
return response()->json([
|
|
594
|
+
'error' => 'MISSING_INVOICE_ID',
|
|
595
|
+
'checkout' => $checkout->public_id,
|
|
596
|
+
'payment' => null,
|
|
597
|
+
]);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
$paymentCheck = $qpay->paymentCheck($invoiceId);
|
|
601
|
+
|
|
602
|
+
if (!$paymentCheck || empty($paymentCheck->count) || $paymentCheck->count < 1) {
|
|
603
|
+
return response()->json([
|
|
604
|
+
'error' => 'PAYMENT_NOTFOUND',
|
|
605
|
+
'checkout' => $checkout->public_id,
|
|
606
|
+
'payment' => null,
|
|
607
|
+
]);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
$payment = data_get($paymentCheck, 'rows.0');
|
|
611
|
+
if ($payment) {
|
|
612
|
+
$data = [
|
|
613
|
+
'checkout' => $checkout->public_id,
|
|
614
|
+
'payment' => (array) $payment,
|
|
615
|
+
'error' => null,
|
|
616
|
+
];
|
|
617
|
+
|
|
618
|
+
SocketClusterService::publish('checkout.' . $checkout->public_id, $data);
|
|
619
|
+
|
|
620
|
+
return $shouldRespond ? response()->json($data) : response()->json();
|
|
621
|
+
}
|
|
622
|
+
} catch (\Exception $e) {
|
|
623
|
+
Log::error('[QPAY CHECKOUT ERROR]: ' . $e->getMessage(), ['checkout' => $checkout->toArray()]);
|
|
624
|
+
if ($shouldRespond) {
|
|
625
|
+
return response()->apiError($e->getMessage());
|
|
557
626
|
}
|
|
558
627
|
}
|
|
559
628
|
|
|
@@ -738,6 +807,18 @@ class CheckoutController extends Controller
|
|
|
738
807
|
$origin = Arr::first($origin);
|
|
739
808
|
}
|
|
740
809
|
|
|
810
|
+
// Check if the order origin is from a food truck via cart property
|
|
811
|
+
$foodTruck = collect($cart->items)
|
|
812
|
+
->map(function ($cartItem) {
|
|
813
|
+
return data_get($cartItem, 'food_truck_id');
|
|
814
|
+
})
|
|
815
|
+
->unique()
|
|
816
|
+
->filter()
|
|
817
|
+
->map(function ($foodTruckId) {
|
|
818
|
+
return FoodTruck::where('public_id', $foodTruckId)->first();
|
|
819
|
+
})
|
|
820
|
+
->first();
|
|
821
|
+
|
|
741
822
|
// if there is no origin attempt to get from cart
|
|
742
823
|
if (!$origin) {
|
|
743
824
|
$storeLocation = collect($cart->items)->map(function ($cartItem) {
|
|
@@ -818,6 +899,11 @@ class CheckoutController extends Controller
|
|
|
818
899
|
...$transactionDetails,
|
|
819
900
|
]);
|
|
820
901
|
|
|
902
|
+
// if there is a food truck include it in the order meta
|
|
903
|
+
if ($foodTruck) {
|
|
904
|
+
$orderMeta['food_truck_id'] = $foodTruck->public_id;
|
|
905
|
+
}
|
|
906
|
+
|
|
821
907
|
// initialize order creation input
|
|
822
908
|
$orderInput = [
|
|
823
909
|
'company_uuid' => $store->company_uuid ?? session('company'),
|
|
@@ -5,6 +5,7 @@ namespace Fleetbase\Storefront\Http\Controllers\v1;
|
|
|
5
5
|
use Fleetbase\Http\Controllers\Controller;
|
|
6
6
|
use Fleetbase\Storefront\Http\Resources\FoodTruck as FoodTruckResource;
|
|
7
7
|
use Fleetbase\Storefront\Models\FoodTruck;
|
|
8
|
+
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
8
9
|
use Illuminate\Http\Request;
|
|
9
10
|
|
|
10
11
|
class FoodTruckController extends Controller
|
|
@@ -36,4 +37,22 @@ class FoodTruckController extends Controller
|
|
|
36
37
|
|
|
37
38
|
return FoodTruckResource::collection($results);
|
|
38
39
|
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Finds a single Storefront FoodTruck resources.
|
|
43
|
+
*
|
|
44
|
+
* @return \Fleetbase\Http\Resources\EntityCollection
|
|
45
|
+
*/
|
|
46
|
+
public function find($id)
|
|
47
|
+
{
|
|
48
|
+
// find for the food truck
|
|
49
|
+
try {
|
|
50
|
+
$foodTruck = FoodTruck::findRecordOrFail($id);
|
|
51
|
+
} catch (ModelNotFoundException $exception) {
|
|
52
|
+
return response()->error('Food Truck resource not found.');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// response the product resource
|
|
56
|
+
return new FoodTruckResource($foodTruck);
|
|
57
|
+
}
|
|
39
58
|
}
|
|
@@ -20,23 +20,24 @@ class FoodTruck extends FleetbaseResource
|
|
|
20
20
|
public function toArray($request)
|
|
21
21
|
{
|
|
22
22
|
return [
|
|
23
|
-
'id'
|
|
24
|
-
'uuid'
|
|
25
|
-
'public_id'
|
|
26
|
-
'company_uuid'
|
|
27
|
-
'created_by_uuid'
|
|
28
|
-
'store_uuid'
|
|
29
|
-
'service_area_uuid'
|
|
30
|
-
'zone_uuid'
|
|
31
|
-
'vehicle_uuid'
|
|
32
|
-
'vehicle'
|
|
33
|
-
'service_area'
|
|
34
|
-
'zone'
|
|
35
|
-
'catalogs'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
23
|
+
'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
|
|
24
|
+
'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
|
|
25
|
+
'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
|
|
26
|
+
'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
|
|
27
|
+
'created_by_uuid' => $this->when(Http::isInternalRequest(), $this->created_by_uuid),
|
|
28
|
+
'store_uuid' => $this->when(Http::isInternalRequest(), $this->store_uuid),
|
|
29
|
+
'service_area_uuid' => $this->when(Http::isInternalRequest(), $this->service_area_uuid),
|
|
30
|
+
'zone_uuid' => $this->when(Http::isInternalRequest(), $this->zone_uuid),
|
|
31
|
+
'vehicle_uuid' => $this->when(Http::isInternalRequest(), $this->vehicle_uuid),
|
|
32
|
+
'vehicle' => $this->vehicle ? new VehicleResource($this->vehicle) : null,
|
|
33
|
+
'service_area' => $this->serviceArea ? new ServiceAreaResource($this->serviceArea) : null,
|
|
34
|
+
'zone' => $this->zone ? new ZoneResource($this->zone) : null,
|
|
35
|
+
'catalogs' => Catalog::collection($this->catalogs ?? []),
|
|
36
|
+
'location' => $this->vehicle ? $this->vehicle->location : null,
|
|
37
|
+
'online' => $this->vehicle ? $this->vehicle->online : false,
|
|
38
|
+
'status' => $this->status,
|
|
39
|
+
'created_at' => $this->created_at,
|
|
40
|
+
'updated_at' => $this->updated_at,
|
|
40
41
|
];
|
|
41
42
|
}
|
|
42
43
|
}
|