From 2b8cbdf1ace87e44a1ef8e5222e8d8b9c0a5753b Mon Sep 17 00:00:00 2001 From: TL Date: Thu, 5 Jan 2023 10:04:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=B8=E5=AE=A2=E7=BB=93=E8=B4=A6=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Middleware/ShopAuthenticate.php | 5 +- beike/Models/Cart.php | 2 +- beike/Models/CartProduct.php | 2 +- beike/Repositories/AddressRepo.php | 2 + beike/Repositories/CartRepo.php | 34 +++++++--- beike/Repositories/OrderRepo.php | 46 ++++++------- beike/Shop/Services/CartService.php | 24 ++++--- beike/Shop/Services/CheckoutService.php | 65 +++++++++++++++---- .../2022_12_30_165725_guest_checkout.php | 41 ++++++++++++ 9 files changed, 168 insertions(+), 53 deletions(-) create mode 100644 database/migrations/2022_12_30_165725_guest_checkout.php diff --git a/app/Http/Middleware/ShopAuthenticate.php b/app/Http/Middleware/ShopAuthenticate.php index 88a90d05..1ff4807f 100644 --- a/app/Http/Middleware/ShopAuthenticate.php +++ b/app/Http/Middleware/ShopAuthenticate.php @@ -25,7 +25,7 @@ class ShopAuthenticate extends Middleware $this->authenticate($request, $guards); $customer = current_customer(); - if ($customer->status != 1) { + if ($customer && $customer->status != 1) { Auth::guard(Customer::AUTH_GUARD)->logout(); return redirect(shop_route('login.index')); } @@ -58,6 +58,9 @@ class ShopAuthenticate extends Middleware */ protected function unauthenticated($request, array $guards) { + if (system_setting('base.guest_checkout', 1)) { + return; + } throw new AuthenticationException( trans('common.unauthenticated'), $guards, $this->redirectTo($request) ); diff --git a/beike/Models/Cart.php b/beike/Models/Cart.php index 7885780f..8a7a32de 100644 --- a/beike/Models/Cart.php +++ b/beike/Models/Cart.php @@ -10,7 +10,7 @@ class Cart extends Base use HasFactory; protected $fillable = [ - 'customer_id', 'shipping_address_id', 'shipping_method_code', 'payment_address_id', 'payment_method_code', 'extra' + 'customer_id', 'session_id', 'shipping_address_id', 'guest_shipping_address', 'shipping_method_code', 'payment_address_id', 'guest_payment_address', 'payment_method_code', 'extra' ]; public function customer(): BelongsTo diff --git a/beike/Models/CartProduct.php b/beike/Models/CartProduct.php index 7d0c486a..4475e302 100644 --- a/beike/Models/CartProduct.php +++ b/beike/Models/CartProduct.php @@ -18,7 +18,7 @@ class CartProduct extends Base { use HasFactory; - protected $fillable = ['customer_id', 'selected', 'product_id', 'product_sku_id', 'quantity']; + protected $fillable = ['customer_id', 'session_id', 'selected', 'product_id', 'product_sku_id', 'quantity']; public function sku(): BelongsTo { diff --git a/beike/Repositories/AddressRepo.php b/beike/Repositories/AddressRepo.php index c4d38892..ef1f5cc0 100644 --- a/beike/Repositories/AddressRepo.php +++ b/beike/Repositories/AddressRepo.php @@ -78,6 +78,8 @@ class AddressRepo } if ($customer) { return $customer->addresses()->with('country')->get(); + } else { + return collect(); } } } diff --git a/beike/Repositories/CartRepo.php b/beike/Repositories/CartRepo.php index 57a8e087..07860ae6 100644 --- a/beike/Repositories/CartRepo.php +++ b/beike/Repositories/CartRepo.php @@ -31,8 +31,13 @@ class CartRepo if (is_numeric($customer)) { $customer = Customer::query()->find($customer); } - $customerId = $customer->id; - $cart = Cart::query()->where('customer_id', $customerId)->first(); + $customerId = $customer->id ?? 0; + $sessionId = session()->getId(); + if ($customerId) { + $cart = Cart::query()->where('customer_id', $customerId)->first(); + } else { + $cart = Cart::query()->where('session_id', $sessionId)->first(); + } $defaultAddress = AddressRepo::listByCustomer($customer)->first(); $defaultAddressId = $defaultAddress->id ?? 0; @@ -42,6 +47,7 @@ class CartRepo $shippingMethodCode = $shippingMethod->code ?? ''; $cart = Cart::query()->create([ 'customer_id' => $customerId, + 'session_id' => $sessionId, 'shipping_address_id' => $defaultAddressId, 'shipping_method_code' => $shippingMethodCode ? $shippingMethodCode . '.0' : '', 'payment_address_id' => $defaultAddressId, @@ -58,6 +64,8 @@ class CartRepo } $cart->loadMissing(['shippingAddress', 'paymentAddress']); $cart->extra = json_decode($cart->extra, true); + $cart->guest_shipping_address = json_decode($cart->guest_shipping_address, true); + $cart->guest_payment_address = json_decode($cart->guest_payment_address, true); return $cart; } @@ -72,8 +80,12 @@ class CartRepo if (is_numeric($customer)) { $customer = Customer::query()->find($customer); } - $customerId = $customer->id; - Cart::query()->where('customer_id', $customerId)->delete(); + $customerId = $customer->id ?? 0; + if ($customer) { + Cart::query()->where('customer_id', $customerId)->delete(); + } else { + Cart::query()->where('session_id', session()->getId())->delete(); + } self::selectedCartProductsBuilder($customerId)->delete(); } @@ -110,9 +122,15 @@ class CartRepo */ public static function allCartProductsBuilder($customerId): Builder { - return CartProduct::query() - ->with(['product.description', 'sku.product.description']) - ->where('customer_id', $customerId) - ->orderByDesc('id'); + $builder = CartProduct::query() + ->with(['product.description', 'sku.product.description']); + if ($customerId) { + $builder->where('customer_id', $customerId); + } else { + $builder->where('session_id', session()->getId()); + } + $builder->orderByDesc('id'); + + return $builder; } } diff --git a/beike/Repositories/OrderRepo.php b/beike/Repositories/OrderRepo.php index 98a62f62..1a0a4600 100644 --- a/beike/Repositories/OrderRepo.php +++ b/beike/Repositories/OrderRepo.php @@ -44,7 +44,7 @@ class OrderRepo public static function getListByCustomer($customer): LengthAwarePaginator { $builder = self::getListBuilder(['customer' => $customer])->orderByDesc('created_at'); - return $builder->paginate(perPage()); + return $builder->paginate(); } @@ -69,7 +69,7 @@ class OrderRepo public static function filterOrders(array $filters = []): LengthAwarePaginator { $builder = self::getListBuilder($filters)->orderByDesc('created_at'); - return $builder->paginate(perPage()); + return $builder->paginate(); } @@ -134,11 +134,14 @@ class OrderRepo */ public static function getOrderByNumber($number, $customer) { - return Order::query() + $builder = Order::query() ->with(['orderProducts', 'orderTotals', 'orderHistories']) - ->where('number', $number) - ->where('customer_id', $customer->id) - ->first(); + ->where('number', $number); + if ($customer) { + $builder->where('customer_id', $customer->id); + } + ; + return $builder->first(); } @@ -175,11 +178,16 @@ class OrderRepo $totals = $data['totals'] ?? []; $orderTotal = collect($totals)->where('code', 'order_total')->first(); - $shippingAddressId = $current['shipping_address_id'] ?? 0; - $paymentAddressId = $current['payment_address_id'] ?? 0; + if (current_customer()) { + $shippingAddressId = $current['shipping_address_id'] ?? 0; + $paymentAddressId = $current['payment_address_id'] ?? 0; - $shippingAddress = Address::query()->findOrFail($shippingAddressId); - $paymentAddress = Address::query()->findOrFail($paymentAddressId); + $shippingAddress = Address::query()->findOrFail($shippingAddressId); + $paymentAddress = Address::query()->findOrFail($paymentAddressId); + } else { + $shippingAddress = (Object)($current['guest_shipping_address'] ?? []); + $paymentAddress = (Object)($current['guest_payment_address'] ?? []); + } $shippingMethodCode = $current['shipping_method_code'] ?? ''; $paymentMethodCode = $current['payment_method_code'] ?? ''; @@ -190,12 +198,12 @@ class OrderRepo $order = new Order([ 'number' => self::generateOrderNumber(), - 'customer_id' => $customer->id, - 'customer_group_id' => $customer->customer_group_id, - 'shipping_address_id' => $shippingAddress->id, - 'payment_address_id' => $paymentAddress->id, - 'customer_name' => $customer->name, - 'email' => $customer->email, + 'customer_id' => $customer->id ?? 0, + 'customer_group_id' => $customer->customer_group_id ?? 0, + 'shipping_address_id' => $shippingAddress->id ?? 0, + 'payment_address_id' => $paymentAddress->id ?? 0, + 'customer_name' => $customer->name ?? '', + 'email' => $customer ? $customer->email : $shippingAddress->email, 'calling_code' => $customer->calling_code ?? 0, 'telephone' => $customer->telephone ?? '', 'total' => $orderTotal['amount'], @@ -211,26 +219,20 @@ class OrderRepo 'shipping_calling_code' => $shippingAddress->calling_code ?? 0, 'shipping_telephone' => $shippingAddress->phone ?? '', 'shipping_country' => $shippingAddress->country->name ?? '', - 'shipping_country_id' => $shippingAddress->country->id ?? 0, 'shipping_zone' => $shippingAddress->zone, - 'shipping_zone_id' => $shippingAddress->zone_id ?? 0, 'shipping_city' => $shippingAddress->city, 'shipping_address_1' => $shippingAddress->address_1, 'shipping_address_2' => $shippingAddress->address_2, - 'shipping_zipcode' => $shippingAddress->zipcode, 'payment_method_code' => $paymentMethodCode, 'payment_method_name' => trans($paymentMethodCode), 'payment_customer_name' => $paymentAddress->name, 'payment_calling_code' => $paymentAddress->calling_code ?? 0, 'payment_telephone' => $paymentAddress->phone ?? '', 'payment_country' => $paymentAddress->country->name ?? '', - 'payment_country_id' => $paymentAddress->country->id ?? 0, 'payment_zone' => $paymentAddress->zone, - 'payment_zone_id' => $paymentAddress->zone_id ?? 0, 'payment_city' => $paymentAddress->city, 'payment_address_1' => $paymentAddress->address_1, 'payment_address_2' => $paymentAddress->address_2, - 'payment_zipcode' => $paymentAddress->zipcode, ]); $order->saveOrFail(); diff --git a/beike/Shop/Services/CartService.php b/beike/Shop/Services/CartService.php index 1807dd50..c9c737c0 100644 --- a/beike/Shop/Services/CartService.php +++ b/beike/Shop/Services/CartService.php @@ -27,10 +27,7 @@ class CartService */ public static function list($customer, bool $selected = false): array { - if (empty($customer)) { - return []; - } - $cartBuilder = CartRepo::allCartProductsBuilder($customer->id); + $cartBuilder = CartRepo::allCartProductsBuilder($customer->id ?? 0); if ($selected) { $cartBuilder->where('selected', true); } @@ -62,9 +59,12 @@ class CartService if (empty($sku) || $quantity == 0) { return null; } - $cart = CartProduct::query() - ->where('customer_id', $customerId) - ->where('product_id', $productId) + if ($customerId) { + $builder = CartProduct::query()->where('customer_id', $customerId); + } else { + $builder = CartProduct::query()->where('session_id', session()->getId()); + } + $cart = $builder->where('product_id', $productId) ->where('product_sku_id', $skuId) ->first(); @@ -74,6 +74,7 @@ class CartService } else { $cart = CartProduct::query()->create([ 'customer_id' => $customerId, + 'session_id' => session()->getId(), 'product_id' => $productId, 'product_sku_id' => $skuId, 'quantity' => $quantity, @@ -127,8 +128,13 @@ class CartService if (empty($cartId)) { return; } - CartProduct::query()->where('customer_id', $customer->id) - ->where('id', $cartId) + $customerId = $customer->id ?? 0; + if ($customerId) { + $builder = CartProduct::query()->where('customer_id', $customerId); + } else { + $builder = CartProduct::query()->orWhere('session_id', session()->getId()); + } + $builder->where('id', $cartId) ->delete(); } diff --git a/beike/Shop/Services/CheckoutService.php b/beike/Shop/Services/CheckoutService.php index 6b216a7a..542ca1bf 100644 --- a/beike/Shop/Services/CheckoutService.php +++ b/beike/Shop/Services/CheckoutService.php @@ -11,9 +11,11 @@ namespace Beike\Shop\Services; +use Beike\Models\Country; use Beike\Models\Order; use Beike\Models\Address; use Beike\Models\Customer; +use Beike\Models\Zone; use Beike\Repositories\CartRepo; use Beike\Repositories\OrderRepo; use Illuminate\Support\Facades\DB; @@ -41,11 +43,11 @@ class CheckoutService if (is_int($customer) || empty($customer)) { $this->customer = current_customer(); } - if (empty($this->customer) || !($this->customer instanceof Customer)) { - throw new \Exception(trans('shop/carts.invalid_customer')); - } + // if (empty($this->customer) || !($this->customer instanceof Customer)) { + // // throw new \Exception(trans('shop/carts.invalid_customer')); + // } $this->cart = CartRepo::createCart($this->customer); - $this->selectedProducts = CartRepo::selectedCartProducts($this->customer->id); + $this->selectedProducts = CartRepo::selectedCartProducts($this->customer->id ?? 0); if ($this->selectedProducts->count() == 0) { throw new \Exception(trans('shop/carts.empty_selected_products')); } @@ -66,6 +68,9 @@ class CheckoutService $paymentAddressId = $requestData['payment_address_id'] ?? 0; $paymentMethodCode = $requestData['payment_method_code'] ?? ''; + $guestShippingAddress = $requestData['guest_shipping_address'] ?? []; + $guestPaymentAddress = $requestData['guest_payment_address'] ?? []; + if ($shippingAddressId) { $this->updateShippingAddressId($shippingAddressId); } @@ -79,6 +84,12 @@ class CheckoutService if ($paymentMethodCode) { $this->updatePaymentMethod($paymentMethodCode); } + if ($guestShippingAddress) { + $this->updateGuestShippingAddress($guestShippingAddress); + } + if ($guestPaymentAddress) { + $this->updateGuestPaymentAddress($guestPaymentAddress); + } hook_action('after_checkout_update', ['request_data' => $requestData, 'cart' => $this->cart]); @@ -137,14 +148,24 @@ class CheckoutService { $current = $checkoutData['current']; - $shippingAddressId = $current['shipping_address_id']; - if (empty(Address::query()->find($shippingAddressId))) { - throw new \Exception(trans('shop/carts.invalid_shipping_address')); - } + if ($this->customer) { + $shippingAddressId = $current['shipping_address_id']; + if (empty(Address::query()->find($shippingAddressId))) { + throw new \Exception(trans('shop/carts.invalid_shipping_address')); + } - $paymentAddressId = $current['payment_address_id']; - if (empty(Address::query()->find($paymentAddressId))) { - throw new \Exception(trans('shop/carts.invalid_payment_address')); + $paymentAddressId = $current['payment_address_id']; + if (empty(Address::query()->find($paymentAddressId))) { + throw new \Exception(trans('shop/carts.invalid_payment_address')); + } + } else { + if (!$current['guest_shipping_address']) { + throw new \Exception(trans('shop/carts.invalid_shipping_address')); + } + + if (!$current['guest_payment_address']) { + throw new \Exception(trans('shop/carts.invalid_payment_address')); + } } $shippingMethodCode = $current['shipping_method_code']; @@ -171,6 +192,16 @@ class CheckoutService $this->cart->update(['payment_address_id' => $paymentAddressId]); } + private function updateGuestShippingAddress($guestShippingAddress) + { + $this->cart->update(['guest_shipping_address' => self::formatAddress($guestShippingAddress)]); + } + + private function updateGuestPaymentAddress($guestPaymentAddress) + { + $this->cart->update(['guest_payment_address' => self::formatAddress($guestPaymentAddress)]); + } + private function updateShippingMethod($shippingMethodCode) { $this->cart->update(['shipping_method_code' => $shippingMethodCode]); @@ -204,8 +235,10 @@ class CheckoutService $data = [ 'current' => [ 'shipping_address_id' => $currentCart->shipping_address_id, + 'guest_shipping_address' => $currentCart->guest_shipping_address, 'shipping_method_code' => $currentCart->shipping_method_code, 'payment_address_id' => $currentCart->payment_address_id, + 'guest_payment_address' => $currentCart->guest_payment_address, 'payment_method_code' => $currentCart->payment_method_code, 'extra' => $currentCart->extra, ], @@ -221,4 +254,14 @@ class CheckoutService return hook_filter('checkout.data', $data); } + + static public function formatAddress($address) + { + if (!$address) { + return []; + } + $address['country'] = Country::find($address['country_id'])->name; + $address['zone'] = Zone::find($address['zone_id'])->name; + return $address; + } } diff --git a/database/migrations/2022_12_30_165725_guest_checkout.php b/database/migrations/2022_12_30_165725_guest_checkout.php new file mode 100644 index 00000000..ecfb587f --- /dev/null +++ b/database/migrations/2022_12_30_165725_guest_checkout.php @@ -0,0 +1,41 @@ +string('session_id')->default('')->after('customer_id'); + $table->json('guest_shipping_address')->nullable()->after('shipping_address_id'); + $table->json('guest_payment_address')->nullable()->after('payment_address_id'); + }); + Schema::table('cart_products', function (Blueprint $table) { + $table->string('session_id')->default('')->after('customer_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + if (!Schema::hasColumn('carts', 'extra')) { + return; + } + } +};