I cart methods
This commit is contained in:
parent
e687836024
commit
7a26c9a965
|
|
@ -221,11 +221,15 @@ class Cart extends Model
|
||||||
$this->validateDateAvailability($from, $until);
|
$this->validateDateAvailability($from, $until);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update cart with from/until
|
||||||
$this->update([
|
$this->update([
|
||||||
'from_date' => $from,
|
'from_date' => $from,
|
||||||
'until_date' => $until,
|
'until_date' => $until,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Update cart items with from/until
|
||||||
|
$this->applyDatesToItems($validateAvailability);
|
||||||
|
|
||||||
return $this->fresh();
|
return $this->fresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -792,14 +796,18 @@ class Cart extends Model
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function validateForCheckout(): void
|
public function validateForCheckout(bool $throws = true): bool
|
||||||
{
|
{
|
||||||
$items = $this->items()
|
$items = $this->items()
|
||||||
->with('purchasable')
|
->with('purchasable')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
if ($items->isEmpty()) {
|
if ($items->isEmpty()) {
|
||||||
throw new \Exception("Cart is empty");
|
if ($throws) {
|
||||||
|
throw new \Exception("Cart is empty");
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that all items have required information before checkout
|
// Validate that all items have required information before checkout
|
||||||
|
|
@ -809,9 +817,16 @@ class Cart extends Model
|
||||||
$product = $item->purchasable;
|
$product = $item->purchasable;
|
||||||
$productName = $product ? $product->name : 'Unknown Product';
|
$productName = $product ? $product->name : 'Unknown Product';
|
||||||
$missingFields = implode(', ', array_keys($adjustments));
|
$missingFields = implode(', ', array_keys($adjustments));
|
||||||
throw new \Exception("Cart item '{$productName}' is missing required information: {$missingFields}");
|
|
||||||
|
if ($throws) {
|
||||||
|
throw new \Exception("Cart item '{$productName}' is missing required information: {$missingFields}");
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkout(): static
|
public function checkout(): static
|
||||||
|
|
@ -926,10 +941,12 @@ class Cart extends Model
|
||||||
* - Returns the Stripe checkout session
|
* - Returns the Stripe checkout session
|
||||||
*
|
*
|
||||||
* @param array $options Optional session parameters (success_url, cancel_url, etc.)
|
* @param array $options Optional session parameters (success_url, cancel_url, etc.)
|
||||||
|
* @param string|null $url Optional fullPath URL for success and cancel URLs
|
||||||
|
*
|
||||||
* @return mixed Stripe\Checkout\Session instance
|
* @return mixed Stripe\Checkout\Session instance
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function checkoutSession(array $options = [])
|
public function checkoutSession(array $options = [], ?string $url = null)
|
||||||
{
|
{
|
||||||
if (!config('shop.stripe.enabled')) {
|
if (!config('shop.stripe.enabled')) {
|
||||||
throw new \Exception('Stripe is not enabled');
|
throw new \Exception('Stripe is not enabled');
|
||||||
|
|
@ -974,13 +991,24 @@ class Cart extends Model
|
||||||
$lineItems[] = $lineItem;
|
$lineItems[] = $lineItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$success_url = $url ?? $options['success_url'] ?? route('shop.stripe.success');
|
||||||
|
$cancel_url = $url ?? $options['cancel_url'] ?? route('shop.stripe.cancel');
|
||||||
|
|
||||||
|
$success_url = (strpos($success_url, '?'))
|
||||||
|
? $success_url . '&session_id={CHECKOUT_SESSION_ID}&cart_id=' . $this->id
|
||||||
|
: $success_url . '?session_id={CHECKOUT_SESSION_ID}&cart_id=' . $this->id;
|
||||||
|
|
||||||
|
$cancel_url = (strpos($cancel_url, '?'))
|
||||||
|
? $cancel_url . '&cart_id=' . $this->id
|
||||||
|
: $cancel_url . '?cart_id=' . $this->id;
|
||||||
|
|
||||||
// Prepare session parameters
|
// Prepare session parameters
|
||||||
$sessionParams = [
|
$sessionParams = [
|
||||||
'payment_method_types' => ['card'],
|
'payment_method_types' => ['card'],
|
||||||
'line_items' => $lineItems,
|
'line_items' => $lineItems,
|
||||||
'mode' => 'payment',
|
'mode' => 'payment',
|
||||||
'success_url' => $options['success_url'] ?? route('shop.stripe.success') . '?session_id={CHECKOUT_SESSION_ID}&cart_id=' . $this->id,
|
'success_url' => $success_url,
|
||||||
'cancel_url' => $options['cancel_url'] ?? route('shop.stripe.cancel') . '?cart_id=' . $this->id,
|
'cancel_url' => $cancel_url,
|
||||||
'client_reference_id' => $this->id,
|
'client_reference_id' => $this->id,
|
||||||
'metadata' => array_merge([
|
'metadata' => array_merge([
|
||||||
'cart_id' => $this->id,
|
'cart_id' => $this->id,
|
||||||
|
|
@ -1038,56 +1066,25 @@ class Cart extends Model
|
||||||
*
|
*
|
||||||
* @return string|null|false
|
* @return string|null|false
|
||||||
*/
|
*/
|
||||||
public function checkoutSessionLink(): string|null|false
|
public function checkoutSessionLink(array $option = [], ?string $url = null): string|null|false
|
||||||
{
|
{
|
||||||
// Check if Stripe is enabled
|
if (! @$this->validateForCheckout(false)) {
|
||||||
if (!config('shop.stripe.enabled')) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if cart has a stored session ID in meta
|
$checkoutSession = $this->checkoutSession($option, $url);
|
||||||
$meta = $this->meta;
|
|
||||||
if (is_array($meta)) {
|
|
||||||
$meta = (object)$meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($meta->stripe_session_id)) {
|
if ($checkoutSession) {
|
||||||
return null;
|
if (
|
||||||
}
|
isset($checkoutSession->url)
|
||||||
|
&& !empty($checkoutSession->url)
|
||||||
$sessionId = $meta->stripe_session_id;
|
) {
|
||||||
|
return $checkoutSession->url;
|
||||||
try {
|
|
||||||
// Ensure Stripe is initialized
|
|
||||||
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
|
|
||||||
|
|
||||||
// Retrieve the session from Stripe
|
|
||||||
$session = \Stripe\Checkout\Session::retrieve($sessionId);
|
|
||||||
|
|
||||||
// Check if session is still valid (not expired)
|
|
||||||
// Stripe sessions expire after 24 hours
|
|
||||||
if (isset($session->expires_at) && $session->expires_at < time()) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the session URL
|
|
||||||
return $session->url ?? null;
|
|
||||||
} catch (\Stripe\Exception\InvalidRequestException $e) {
|
|
||||||
// Session not found or invalid
|
|
||||||
\Illuminate\Support\Facades\Log::warning('Stripe session not found', [
|
|
||||||
'cart_id' => $this->id,
|
|
||||||
'session_id' => $sessionId,
|
|
||||||
'error' => $e->getMessage(),
|
|
||||||
]);
|
|
||||||
return null;
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// Other errors
|
|
||||||
\Illuminate\Support\Facades\Log::error('Error retrieving Stripe checkout session', [
|
|
||||||
'cart_id' => $this->id,
|
|
||||||
'session_id' => $sessionId,
|
|
||||||
'error' => $e->getMessage(),
|
|
||||||
]);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -234,15 +234,13 @@ class CartTest extends TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function checkout_session_link_returns_null_when_stripe_disabled()
|
public function checkout_session_link_is_null_when_stripe_disabled()
|
||||||
{
|
{
|
||||||
config(['shop.stripe.enabled' => false]);
|
config(['shop.stripe.enabled' => false]);
|
||||||
|
|
||||||
$cart = Cart::create();
|
$cart = Cart::create();
|
||||||
|
|
||||||
$link = $cart->checkoutSessionLink();
|
$this->assertNull($cart->checkoutSessionLink());
|
||||||
|
|
||||||
$this->assertNull($link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue