Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ jobs:
if [ "$STATUS" == "ACTIVE" ]; then
echo "✅ Deployment completed successfully."
exit 0
elif [[ "$STATUS" == "FAILED" || "$STATUS" == "CANCELLED" ]]; then
elif [[ "$STATUS" == "FAILED" || "$STATUS" == "CANCELED" ]]; then
echo "❌ Deployment failed or was cancelled."
exit 1
fi
Expand Down
13 changes: 13 additions & 0 deletions backend/app/DomainObjects/OrderDomainObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class OrderDomainObject extends Generated\OrderDomainObjectAbstract implements I

public ?EventDomainObject $event = null;

public ?string $sessionIdentifier = null;

public static function getAllowedFilterFields(): array
{
return [
Expand Down Expand Up @@ -253,4 +255,15 @@ public function getInvoices(): ?Collection
{
return $this->invoices;
}

public function setSessionIdentifier(?string $sessionIdentifier): OrderDomainObject
{
$this->sessionIdentifier = $sessionIdentifier;
return $this;
}

public function getSessionIdentifier(): ?string
{
return $this->sessionIdentifier;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ public function __invoke(CreateOrderRequest $request, int $eventId): JsonRespons
])
);

$order->setSessionIdentifier($sessionId);

$response = $this->resourceResponse(
resource: OrderResourcePublic::class,
data: $order,
statusCode: ResponseCodes::HTTP_CREATED
statusCode: ResponseCodes::HTTP_CREATED,
);

return $response->withCookie(
Expand Down
14 changes: 12 additions & 2 deletions backend/app/Http/Actions/Orders/Public/GetOrderActionPublic.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
use HiEvents\Resources\Order\OrderResourcePublic;
use HiEvents\Services\Application\Handlers\Order\DTO\GetOrderPublicDTO;
use HiEvents\Services\Application\Handlers\Order\GetOrderPublicHandler;
use HiEvents\Services\Infrastructure\Session\CheckoutSessionManagementService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class GetOrderActionPublic extends BaseAction
{
public function __construct(
private readonly GetOrderPublicHandler $getOrderPublicHandler
private readonly GetOrderPublicHandler $getOrderPublicHandler,
private readonly CheckoutSessionManagementService $sessionService,
)
{
}
Expand All @@ -25,9 +27,17 @@ public function __invoke(int $eventId, string $orderShortId, Request $request):
includeEventInResponse: $this->isIncludeRequested($request, 'event'),
));

return $this->resourceResponse(
$response = $this->resourceResponse(
resource: OrderResourcePublic::class,
data: $order,
);

if ($request->query->has('session_identifier')) {
$response->headers->setCookie(
$this->sessionService->getSessionCookie()
);
}

return $response;
}
}
4 changes: 3 additions & 1 deletion backend/app/Resources/Order/OrderResourcePublic.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use HiEvents\Resources\Attendee\AttendeeResourcePublic;
use HiEvents\Resources\BaseResource;
use HiEvents\Resources\Event\EventResourcePublic;
use HiEvents\Resources\Order\Invoice\InvoiceResource;
use HiEvents\Resources\Order\Invoice\InvoiceResourcePublic;
use Illuminate\Http\Request;

Expand Down Expand Up @@ -64,6 +63,9 @@ public function toArray(Request $request): array
!is_null($this->getAttendees()),
fn() => AttendeeResourcePublic::collection($this->getAttendees())
),
$this->mergeWhen($this->getSessionIdentifier() !== null, fn() => [
'session_identifier' => $this->getSessionIdentifier(),
]),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ public function __construct(
}

/**
* Get the session ID from the cookie, or generate a new one if it doesn't exist.
* Get the session ID from query param, cookie, or generate a new one.
*/
public function getSessionId(): string
{
if ($this->sessionId) {
return $this->sessionId;
}

$this->sessionId = $this->request->cookie(self::SESSION_IDENTIFIER) ?? $this->createSessionId();
$this->sessionId = $this->request->query(self::SESSION_IDENTIFIER)
?? $this->request->cookie(self::SESSION_IDENTIFIER)
?? $this->createSessionId();

return $this->sessionId;
}
Expand Down
24 changes: 20 additions & 4 deletions frontend/src/api/order.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,36 @@ export const orderClientPublic = {
return response.data;
},

findByShortId: async (eventId: number, orderShortId: string, includes: string[] = []) => {
const response = await publicApi.get<GenericDataResponse<Order>>(`events/${eventId}/order/${orderShortId}?include=${includes.join(',')}`);
findByShortId: async (
eventId: number,
orderShortId: string,
includes: string[] = [],
sessionIdentifier?: string
) => {
const query = new URLSearchParams();
if (includes.length > 0) {
query.append("include", includes.join(","));
}
if (sessionIdentifier) {
query.append("session_identifier", sessionIdentifier);
}

const response = await publicApi.get<GenericDataResponse<Order>>(
`events/${eventId}/order/${orderShortId}?${query.toString()}`
);

return response.data;
},

findOrderStripePaymentIntent: async (eventId: number, orderShortId: string) => {
return await publicApi.get<StripePaymentIntent>(`events/${eventId}/order/${orderShortId}/stripe/payment_intent`);
},

createStripePaymentIntent: async (eventId: number, orderShortId: string, sessionIdentifier: string) => {
createStripePaymentIntent: async (eventId: number, orderShortId: string) => {
const response = await publicApi.post<{
client_secret: string,
account_id?: string,
}>(`events/${eventId}/order/${orderShortId}/stripe/payment_intent?session_identifier=${sessionIdentifier}`);
}>(`events/${eventId}/order/${orderShortId}/stripe/payment_intent`);
return response.data;
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ const SelectProducts = (props: SelectProductsProps) => {
.then(() => {
const url = '/checkout/' + eventId + '/' + data.data.short_id + '/details';
if (props.widgetMode === 'embedded') {
window.open(url, '_blank');
window.open(
url + '?session_identifier=' + data.data.session_identifier + '&utm_source=embedded_widget',
'_blank'
);
setOrderInProcessOverlayVisible(true);
return;
}
Expand Down
1 change: 0 additions & 1 deletion frontend/src/queries/useCreateStripePaymentIntent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export const useCreateStripePaymentIntent = (eventId: IdParam, orderShortId: IdP
const {client_secret, account_id} = await orderClientPublic.createStripePaymentIntent(
Number(eventId),
String(orderShortId),
getSessionIdentifier(),
);
return {client_secret, account_id};
},
Expand Down
33 changes: 26 additions & 7 deletions frontend/src/queries/useGetOrderPublic.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
import {useQuery} from "@tanstack/react-query";
import {orderClientPublic} from "../api/order.client.ts";
import {IdParam, Order} from "../types.ts";
import {useMemo} from "react";
import {isSsr} from "../utilites/helpers.ts";

export const GET_ORDER_PUBLIC_QUERY_KEY = 'getOrderPublic';
export const GET_ORDER_PUBLIC_QUERY_KEY = "getOrderPublic";

export const useGetOrderPublic = (eventId: IdParam, orderShortId: IdParam, includes: string[] = []) => {
return useQuery<Order>({
queryKey: [GET_ORDER_PUBLIC_QUERY_KEY, eventId, orderShortId],
const getSessionIdentifierFromUrl = (): string | null => {
if (isSsr()) return null;

const url = new URL(window.location.href);
return url.searchParams.get("session_identifier");
};

export const useGetOrderPublic = (
eventId: IdParam,
orderShortId: IdParam,
includes: string[] = []
) => {
const sessionIdentifier = useMemo(getSessionIdentifierFromUrl, []);

return useQuery<Order>({
queryKey: [
GET_ORDER_PUBLIC_QUERY_KEY,
eventId,
orderShortId,
sessionIdentifier,
],
queryFn: async () => {
const {data} = await orderClientPublic.findByShortId(
Number(eventId),
String(orderShortId),
includes,
sessionIdentifier ?? undefined
);
return data;
},

refetchOnWindowFocus: false,
staleTime: 500,
retryOnMount: false,
retry: false
retry: false,
});
}
};
1 change: 1 addition & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ export interface Order {
question_answers?: QuestionAnswer[];
event?: Event;
latest_invoice?: Invoice;
session_identifier?: string;
}

export interface Invoice {
Expand Down
Loading