// +---------------------------------------------------------------------- namespace app\services\order\cashier; use app\jobs\activity\StorePromotionsJob; use app\jobs\user\MicroPayOrderJob; use app\services\activity\collage\UserCollagePartakeServices; use app\services\activity\collage\UserCollageCodeServices; use app\services\BaseServices; use app\services\activity\coupon\StoreCouponUserServices; use app\services\activity\coupon\StoreCouponIssueServices; use app\services\order\StoreCartServices; use app\services\order\StoreOrderCartInfoServices; use app\services\order\StoreOrderComputedServices; use app\services\order\StoreOrderCreateServices; use app\services\order\StoreOrderSuccessServices; use app\services\pay\PayServices; use app\services\pay\YuePayServices; use app\services\product\branch\StoreBranchProductServices; use app\services\product\product\StoreProductServices; use app\services\product\sku\StoreProductAttrValueServices; use app\services\store\SystemStoreServices; use app\services\store\SystemStoreStaffServices; use app\services\user\level\SystemUserLevelServices; use app\services\user\level\UserLevelServices; use app\services\user\UserAddressServices; use app\services\user\UserInvoiceServices; use app\services\user\UserServices; use crmeb\services\CacheService; use crmeb\traits\OptionTrait; use think\exception\ValidateException; use function Swoole\Coroutine\batch; /** * 收银台订单 * Class CashierOrderServices * @package app\services\order\cashier */ class CashierOrderServices extends BaseServices { use OptionTrait; //余额支付 const YUE_PAY = 1; //线上支付 const ONE_LINE_PAY = 2; //现金支付 const CASH_PAY = 3; /** * 缓存订单信息 * @param int $uid * @param array $cartInfo * @param array $priceGroup * @param array $other * @param array $addr * @param array $invalidCartInfo * @param array $deduction * @param int $cacheTime * @return string * @throws \Psr\SimpleCache\InvalidArgumentException */ public function cacheOrderInfo(int $uid, array $cartInfo, array $priceGroup, array $other = [], array $addr = [], array $invalidCartInfo = [], array $deduction = [], int $cacheTime = 600) { /** @var StoreOrderCreateServices $storeOrderCreateService */ $storeOrderCreateService = app()->make(StoreOrderCreateServices::class); $key = md5($storeOrderCreateService->getNewOrderId((string)$uid) . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8)); CacheService::redisHandler()->set('admin_user_order_' . $uid . $key, compact('cartInfo', 'priceGroup', 'other', 'addr', 'invalidCartInfo', 'deduction'), $cacheTime); return $key; } /** * 获取订单缓存信息 * @param int $uid * @param string $key * @return |null */ public function getCacheOrderInfo(int $uid, string $key) { $cacheName = 'admin_user_order_' . $uid . $key; if (!CacheService::redisHandler()->has($cacheName)) return null; return CacheService::redisHandler()->get($cacheName); } /** * 获取订单确认数据 * @param array $user * @param $cartId * @param bool $new * @param int $addressId * @param int $shipping_type * @param int $store_id * @param int $coupon_id * @return array * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getOrderConfirmData(int $uid, $cartId, bool $new, int $addressId, int $shipping_type = 1, int $coupon_id = 0, int $store_id = 0) { $addr = $data = $user = []; if ($uid) { /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); $user = $userServices->getUserCacheInfo($uid); } /** @var UserAddressServices $addressServices */ $addressServices = app()->make(UserAddressServices::class); if ($addressId) { $addr = $addressServices->getAdderssCache($addressId); } //没传地址id或地址已删除未找到 ||获取默认地址 if (!$addr && $uid) { $addr = $addressServices->getUserDefaultAddressCache($uid); } if ($store_id) { /** @var SystemStoreServices $storeServices */ $storeServices = app()->make(SystemStoreServices::class); $storeServices->getStoreInfo($store_id); } /** @var StoreCartServices $cartServices */ $cartServices = app()->make(StoreCartServices::class); //获取购物车信息 $cartGroup = $cartServices->getUserProductCartListV1($uid, $cartId, $new, $addr, $shipping_type, $store_id, $coupon_id); $storeFreePostage = floatval(sys_config('store_free_postage')) ?: 0;//满额包邮金额 $data['storeFreePostage'] = $storeFreePostage; $validCartInfo = $cartGroup['valid']; $giveCartList = $cartGroup['giveCartList'] ?? []; /** @var StoreOrderComputedServices $computedServices */ $computedServices = app()->make(StoreOrderComputedServices::class); $priceGroup = $computedServices->getOrderPriceGroup($uid, $validCartInfo, $addr, $storeFreePostage); $priceGroup['couponPrice'] = $cartGroup['couponPrice'] ?? 0; $priceGroup['firstOrderPrice'] = $cartGroup['firstOrderPrice'] ?? 0; $validCartInfo = array_merge($priceGroup['cartInfo'] ?? $validCartInfo, $giveCartList); $other = [ 'offlinePostage' => sys_config('offline_postage'), 'integralRatio' => sys_config('integral_ratio'), 'give_integral' => $cartGroup['giveIntegral'] ?? 0, 'give_coupon' => $cartGroup['giveCoupon'] ?? [], 'give_product' => $cartGroup['giveProduct'], 'promotions' => $cartGroup['promotions'] ]; $deduction = $cartGroup['deduction']; $data['product_type'] = $deduction['product_type'] ?? 0; $data['valid_count'] = count($validCartInfo); $data['addressInfo'] = $addr; $data['type'] = $deduction['type'] ?? 0; $data['activity_id'] = $deduction['activity_id'] ?? 0; $data['seckill_id'] = $deduction['type'] == 1 ? $deduction['activity_id'] : 0; $data['bargain_id'] = $deduction['type'] == 2 ? $deduction['activity_id'] : 0; $data['combination_id'] = $deduction['type'] == 3 ? $deduction['activity_id'] : 0; $data['storeIntegralId'] = $deduction['type'] == 4 ? $deduction['activity_id'] : 0; $data['discount_id'] = $deduction['type'] == 5 ? $deduction['activity_id'] : 0; $data['newcomer_id'] = $deduction['type'] == 7 ? $deduction['activity_id'] : 0; $data['deduction'] = in_array($deduction['product_type'], [1, 2]) || $deduction['activity_id'] > 0; $data['cartInfo'] = array_merge($cartGroup['cartInfo'], $giveCartList); // $data['giveCartInfo'] = $giveCartList; $data['custom_form'] = []; $data['give_integral'] = $other['give_integral']; $data['give_coupon'] = []; if ($other['give_coupon']) { /** @var StoreCouponIssueServices $couponIssueService */ $couponIssueService = app()->make(StoreCouponIssueServices::class); $data['give_coupon'] = $couponIssueService->getColumn([['id', 'IN', $other['give_coupon']]], 'id,coupon_title'); } $data['orderKey'] = $this->cacheOrderInfo($uid, $validCartInfo, $priceGroup, $other, $addr, $cartGroup['invalid'] ?? [], $deduction); unset($priceGroup['cartInfo']); $data['priceGroup'] = $priceGroup; $userInfo = ['uid' => $user['uid'] ?? 0, 'nickname' => $user['nickname'] ?? '', 'avatar' => $user['avatar'] ?? '', 'phone' => $user['phone'] ?? '', 'now_money' => $user['now_money'] ?? 0, 'integral' => $user['integral'] ?? 0]; //会员 $userInfo['isMember'] = isset($user['is_money_level']) && $user['is_money_level'] > 0 ? 1 : 0; //等级 $userInfo['level'] = $user['level'] ?? 0; $userInfo['level_status'] = 0; $userInfo['level_grade'] = ''; $userInfo['vip'] = isset($priceGroup['vipPrice']) && $priceGroup['vipPrice'] > 0; $userInfo['vip_id'] = 0; $userInfo['discount'] = 0; //用户等级是否开启 if (sys_config('member_func_status', 1)) { /** @var UserLevelServices $levelServices */ $levelServices = app()->make(UserLevelServices::class); $userLevel = $levelServices->getUerLevelInfoByUid($uid); if ($userInfo['vip'] || $userLevel) { $userInfo['vip'] = true; $userInfo['vip_id'] = $userLevel['id'] ?? 0; $userInfo['discount'] = $userLevel['discount'] ?? 0; } if ($userInfo['level']) { /** @var SystemUserLevelServices $levelServices */ $levelServices = app()->make(SystemUserLevelServices::class); $levelInfo = $levelServices->getOne(['id' => $userInfo['level']], 'id,name,grade'); $userInfo['level_grade'] = $levelInfo['grade'] ?? ''; $userInfo['level_status'] = 1; } } $userInfo['real_name'] = $user['real_name'] ?? $user['nickname'] ?? ''; $userInfo['record_pone'] = $user['record_pone'] ?? $user['phone'] ?? ''; $data['userInfo'] = $userInfo; $data['offlinePostage'] = $other['offlinePostage']; $data['integralRatio'] = $other['integralRatio']; $data['integral_ratio_status'] = (int)(sys_config('integral_ratio_status', 1) && in_array($data['type'], [0, 6])); $data['store_func_status'] = (int)(sys_config('store_func_status', 1));//门店是否开启 $data['store_self_mention'] = false;//门店自提 $data['store_delivery_status'] = false;//门店配送 if ($data['store_func_status']) { //门店自提是否开启 /** @var SystemStoreServices $systemStoreServices */ $systemStoreServices = app()->make(SystemStoreServices::class); $data['store_self_mention'] = sys_config('store_self_mention') && $systemStoreServices->count(['type' => 0, 'is_store' => 1]); $data['store_delivery_status'] = !!$systemStoreServices->count(['type' => 0]); } $data['store_func_status'] = $data['store_func_status'] && ($data['store_self_mention'] || $data['store_delivery_status']); $data['system_store'] = [];//门店信息 /** @var UserInvoiceServices $userInvoice */ $userInvoice = app()->make(UserInvoiceServices::class); $invoice_func = $userInvoice->invoiceFuncStatus(); $data['invoice_func'] = $invoice_func['invoice_func']; $data['special_invoice'] = $invoice_func['special_invoice']; /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); $data['svip_status'] = $svip_status = $userServices->checkUserIsSvip($uid); $svip_price = 0.00; //开启付费会员 且用户不是付费会员 //计算 开通付费会员节省金额 if (sys_config('member_card_status', 1) && !$svip_status) { $payPrice = $cartServices->getPayPrice((string)$priceGroup['totalPrice'], (string)($priceGroup['couponPrice'] ?? 0), (string)($priceGroup['firstOrderPrice'] ?? 0)); [$vipPayPrice, $payPostage, $storePostageDiscount] = $cartServices->computeUserVipCart($uid, $cartId, $shipping_type, $new, $store_id, false, $coupon_id, $addr); $svip_price = (float)max(bcadd((string)bcsub((string)$payPrice, (string)$vipPayPrice, 2), (string)$storePostageDiscount, 2), 0); } $data['svip_price'] = $svip_price; return $data; } /** * 计算某个门店中收银台的金额 * @param int $uid * @param int $storeId * @param array $cartIds * @param bool $integral * @param bool $coupon * @param array $userInfo * @param int $coupon_id * @param bool $new * @param array $cartGroup * @param int $addressId * @param string $payType * @param int $shippingType * @return array * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function computeOrder(int $uid = 0, int $storeId = 0, array $cartIds = [], bool $integral = false, bool $coupon = false, array $userInfo = [], int $coupon_id = 0, bool $new = false, array $cartGroup = [], int $addressId = 0, string $payType = 'yue', int $shippingType = 4) { if (!$userInfo && $uid) { /** @var UserServices $userService */ $userService = app()->make(UserServices::class); $userInfo = $userService->getUserInfo($uid); if (!$userInfo) { throw new ValidateException('用户不存在'); } $userInfo = $userInfo->toArray(); } $payPostage = 0; $storePostageDiscount = 0; $firstOrderPrice = 0; /** @var StoreOrderComputedServices $computeOrderService */ $computeOrderService = app()->make(StoreOrderComputedServices::class); if ($cartGroup && $shippingType != 4) { $cartInfo = $cartGroup['cartInfo']; $priceGroup = $cartGroup['priceGroup']; $deduction = $cartGroup['deduction']; $other = $cartGroup['other']; $promotions = $other['promotions'] ?? []; $payPrice = (float)$priceGroup['totalPrice']; $payIntegral = (int)$priceGroup['totalIntegral'] ?? 0; $couponPrice = (float)$priceGroup['couponPrice']; $firstOrderPrice = (float)$priceGroup['firstOrderPrice']; $sumPrice = $priceGroup['sumPrice'];//获取订单原总金额 $totalPrice = $priceGroup['totalPrice'];//获取订单svip、用户等级优惠之后总金额 $costPrice = $priceGroup['costPrice'];//获取订单成本价 $vipPrice = $priceGroup['vipPrice'];//获取订单会员优惠金额 $promotionsPrice = $computeOrderService->getOrderSumPrice($cartInfo, 'promotions_true_price');//优惠活动优惠 $addr = $cartGroup['addr'] ?? []; $postage = $priceGroup; if (!$addr || $addr['id'] != $addressId) { /** @var UserAddressServices $addressServices */ $addressServices = app()->make(UserAddressServices::class); $addr = $addressServices->getAdderssCache($addressId); //改变地址重新计算邮费 $postage = []; } $type = (int)$deduction['type'] ?? 0; $results = batch([ 'promotions' => function () use ($cartInfo, $type) { $promotionsPrice = 0; if ($type == 8) return $promotionsPrice; foreach ($cartInfo as $key => $cart) { if (isset($cart['promotions_true_price']) && isset($cart['price_type']) && $cart['price_type'] == 'promotions') { $promotionsPrice = bcadd((string)$promotionsPrice, (string)bcmul((string)$cart['promotions_true_price'], (string)$cart['cart_num'], 2), 2); } } return $promotionsPrice; }, 'postage' => function () use ($uid, $shippingType, $payType, $cartInfo, $addr, $payPrice, $postage, $other, $type, $computeOrderService) { return $computeOrderService->computedPayPostage($uid, $shippingType, $payType, $cartInfo, $addr, $payPrice, $postage, $other); }, ]); [$p, $payPostage, $storePostageDiscount, $storeFreePostage, $isStoreFreePostage] = $results['postage']; } else { /** @var StoreCartServices $cartServices */ $cartServices = app()->make(StoreCartServices::class); //获取购物车信息 $cartGroup = $cartServices->getUserProductCartListV1($uid, $cartIds, $new, [], 4, $storeId, $coupon_id); $cartInfo = array_merge($cartGroup['valid'], $cartGroup['giveCartList']); if (!$cartInfo) { throw new ValidateException('购物车暂无货物!'); } $deduction = $cartGroup['deduction']; $promotions = $cartGroup['promotions'] ?? []; $other = [ 'offlinePostage' => sys_config('offline_postage'), 'integralRatio' => sys_config('integral_ratio'), 'give_integral' => $cartGroup['giveIntegral'] ?? 0, 'give_coupon' => $cartGroup['giveCoupon'] ?? [], 'give_product' => $cartGroup['giveProduct'], 'promotions' => $cartGroup['promotions'] ]; $cartGroup['other'] = $other; $sumPrice = $computeOrderService->getOrderSumPrice($cartInfo, 'sum_price');//获取订单原总金额 $totalPrice = $computeOrderService->getOrderSumPrice($cartInfo, 'truePrice');//获取订单svip、用户等级优惠之后总金额 $costPrice = $computeOrderService->getOrderSumPrice($cartInfo, 'costPrice');//获取订单成本价 $vipPrice = $computeOrderService->getOrderSumPrice($cartInfo, 'vip_truePrice');//获取订单会员优惠金额 $promotionsPrice = $computeOrderService->getOrderSumPrice($cartInfo, 'promotions_true_price');//优惠活动优惠 $payPrice = (float)$totalPrice; $couponPrice = floatval($cartGroup['couponPrice'] ?? 0); } $promotionsDetail = []; if ($promotions) { foreach ($promotions as $key => $value) { if (isset($value['details']['sum_promotions_price']) && $value['details']['sum_promotions_price']) { $promotionsDetail[] = ['id' => $value['id'], 'name' => $value['name'], 'title' => $value['title'], 'desc' => $value['desc'], 'promotions_price' => $value['details']['sum_promotions_price'], 'promotions_type' => $value['promotions_type']]; } } if ($promotionsDetail) { $typeArr = array_column($promotionsDetail, 'promotions_type'); array_multisort($typeArr, SORT_ASC, $promotionsDetail); } } $is_cashier_yue_pay_verify = (int)sys_config('is_cashier_yue_pay_verify'); // 收银台余额支付是否需要验证【是/否】 if ($couponPrice < $payPrice) { $payPrice = (float)bcsub((string)$payPrice, (string)$couponPrice, 2); } else { $couponPrice = $payPrice; $payPrice = 0; } if ($firstOrderPrice < $payPrice) {//首单优惠金额 $payPrice = bcsub((string)$payPrice, (string)$firstOrderPrice, 2); } else { $payPrice = 0; } $SurplusIntegral = $usedIntegral = 0; $deductionPrice = '0'; //使用积分 if ($userInfo && $integral) { [ $payPrice, $deductionPrice, $usedIntegral, $SurplusIntegral ] = $computeOrderService->useIntegral(true, $userInfo, $payPrice, [ 'offlinePostage' => sys_config('offline_postage'), 'integralRatio' => sys_config('integral_ratio') ]); } $payPrice = (float)bcadd((string)$payPrice, (string)$payPostage, 2); return [ 'payPrice' => floatval($payPrice),//支付金额 'vipPrice' => floatval($vipPrice),//会员优惠金额 'totalPrice' => floatval($totalPrice),//会员优惠后订单金额 'costPrice' => floatval($costPrice),//成本金额 'sumPrice' => floatval($sumPrice),//订单总金额 'couponPrice' => $couponPrice,//优惠券金额 'pay_postage' => $payPostage ?? 0, 'storePostageDiscount' => $storePostageDiscount ?? 0, 'promotionsPrice' => floatval($promotionsPrice),//优惠活动金额 'promotionsDetail' => $promotionsDetail,//优惠 'deductionPrice' => floatval($deductionPrice),//积分抵扣多少钱 'surplusIntegral' => $SurplusIntegral,//抵扣了多少积分 'usedIntegral' => $usedIntegral,//使用了多少积分 'deduction' => $deduction, 'cartInfo' => $cartInfo,//购物列表 'is_cashier_yue_pay_verify' => $is_cashier_yue_pay_verify,//收银台余额支付验证 1 验证 0不验证 'cartGroup' => $cartGroup//计算结果 ]; } /** * 收银台用户优惠券 * @param int $uid * @param int $storeId * @param array $cartIds * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getCouponList(int $uid, int $storeId, array $cartIds) { /** @var StoreCartServices $cartService */ $cartService = app()->make(StoreCartServices::class); $cart = $cartService->getUserCartList($uid, 1, $cartIds, $storeId, -1, 4, 0, 0, 0, false); $cartInfo = $cart['valid']; if (!$cartInfo) { throw new ValidateException('购物车暂无货物!'); } /** @var StoreCouponissueServices $couponIssueServices */ $couponIssueServices = app()->make(StoreCouponissueServices::class); return $couponIssueServices->getCanUseCoupon($uid, $cartInfo, $cart['promotions'] ?? [], $storeId, false); } /** * 二位数组冒泡排序 * @param array $arr * @param string $key * @return array */ protected function mpSort(array $arr, string $key) { for ($i = 0; $i < count($arr); $i++) { for ($j = $i; $j < count($arr); $j++) { if ($arr[$i][$key] > $arr[$j][$key]) { $temp = $arr[$i]; $arr[$i] = $arr[$j]; $arr[$j] = $temp; } } } return $arr; } /** * 自动解析扫描二维码 * @param string $barCode * @param int $storeId * @param int $uid * @param int $staff_id * @param int $touristUid * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getAnalysisCode(string $barCode, int $storeId, int $uid, int $staff_id, int $touristUid = 0) { /** @var UserServices $userService */ $userService = app()->make(UserServices::class); $userInfo = $userService->get(['bar_code' => $barCode], ['uid', 'avatar', 'nickname', 'now_money', 'integral']); if ($userInfo) { return ['userInfo' => $userInfo->toArray()]; } else { /** @var SystemStoreStaffServices $staffServices */ $staffServices = app()->make(SystemStoreStaffServices::class); $staffServices->getStaffInfo($staff_id); /** @var StoreProductAttrValueServices $storeProductAttrService */ $storeProductAttrService = app()->make(StoreProductAttrValueServices::class); $attProductInfo = $storeProductAttrService->getAttrByBarCode((string)$barCode); if (!$attProductInfo) { throw new ValidateException('没有扫描到商品'); } /** @var StoreProductServices $productService */ $productService = app()->make(StoreProductServices::class); $productInfo = $productService->get(['is_show' => 1, 'is_del' => 0, 'id' => $attProductInfo->product_id], [ 'image', 'store_name', 'store_info', 'bar_code', 'price', 'id as product_id', 'id' ]); if (!$productInfo) { throw new ValidateException('商品未查到'); } /** @var StoreBranchProductServices $storeProductService */ $storeProductService = app()->make(StoreBranchProductServices::class); if (!$storeProductService->count(['store_id' => $storeId, 'product_id' => $attProductInfo->product_id])) { throw new ValidateException('该商品在此门店不存在'); } /** @var StoreProductAttrValueServices $valueService */ $valueService = app()->make(StoreProductAttrValueServices::class); $valueInfo = $valueService->getOne(['unique' => $attProductInfo->unique]); if (!$valueInfo) { throw new ValidateException('商品属性不存在'); } $productInfo = $productInfo->toArray(); $productInfo['attr_value'] = [ 'ot_price' => $valueInfo->ot_price, 'price' => $valueInfo->price, 'sales' => $valueInfo->sales, 'vip_price' => $valueInfo->vip_price, 'stock' => $attProductInfo->stock, ]; if ($uid || $touristUid) { /** @var StoreCartServices $cartService */ $cartService = app()->make(StoreCartServices::class); $cartService->setItem('store_id', $storeId); $cartService->setItem('tourist_uid', $touristUid); $cartId = $cartService->addCashierCart($uid, $attProductInfo->product_id, 1, $attProductInfo->unique, $staff_id); $cartService->reset(); if (!$cartId) { throw new ValidateException('自动添加购物车失败'); } } else { $cartId = 0; } return ['productInfo' => $productInfo, 'cartId' => $cartId]; } } /** * 生成订单 * @param int $uid * @param int $storeId * @param int $staffId * @param array $cartIds * @param string $payType * @param bool $integral * @param bool $coupon * @param string $remarks * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function createOrder(int $uid, array $userInfo, array $computeData, int $storeId, int $staffId, array $cartIds, string $payType, bool $integral = false, bool $coupon = false, string $remarks = '', string $changePrice = '0', bool $isPrice = false, int $coupon_id = 0, int $seckillId = 0, $collate_code_id = 0, int $addressId = 0, array $addressInfo = [], $shippingType = 4, $clerk_id = 0) { /** @var SystemStoreStaffServices $staffService */ $staffService = app()->make(SystemStoreStaffServices::class); $staffInfo = []; if ($storeId && $staffId && !$staffInfo = $staffService->getOne(['store_id' => $storeId, 'id' => $staffId, 'is_del' => 0, 'status' => 1])) { throw new ValidateException('您选择的店员不存在'); } if ($staffInfo) { $clerk_id = $staffInfo['uid']; } if (!$storeId && $staffId) { $clerk_id = $staffId; $staffId = 0; } //兼容门店虚拟用户下单 $field = ['real_name', 'phone', 'province', 'city', 'district', 'street', 'detail']; if ($uid && !$addressId && !$addressInfo) { /** @var UserAddressServices $addreService */ $addreService = app()->make(UserAddressServices::class); $addressInfo = $addreService->getUserDefaultAddress($uid, implode(',', $field)); if ($addressInfo) { $addressInfo = $addressInfo->toArray(); } } if (!$addressInfo) { foreach ($field as $key) { $addressInfo[$key] = ''; } } $cartGroup = $computeData['cartGroup'] ?? []; $cartInfo = $computeData['cartInfo']; $totalPrice = $computeData['totalPrice']; $couponId = $coupon_id; $couponPrice = $computeData['couponPrice'] ?? '0.00'; $useIntegral = $computeData['usedIntegral']; $deduction = $computeData['deduction']; $other = $cartGroup['other']; $gainIntegral = $totalNum = 0; $priceData = [ 'coupon_id' => $couponId, 'coupon_price' => $couponPrice, 'usedIntegral' => $useIntegral, 'deduction_price' => $computeData['deductionPrice'] ?? '0.00', 'promotions_price' => $computeData['promotionsPrice'], 'pay_postage' => 0, 'pay_price' => $computeData['payPrice'] ]; $promotions_give = [ 'give_integral' => $other['give_integral'] ?? 0, 'give_coupon' => $other['give_coupon'] ?? [], 'give_product' => $other['give_product'] ?? [], 'promotions' => $other['promotions'] ?? [] ]; $type = (int)$deduction['type'] ?? 0; $seckillId = $seckillId ?: ($type == 1 ? ($deduction['activity_id'] ?? 0) : 0); foreach ($cartInfo as $cart) { $totalNum += $cart['cart_num']; $cartInfoGainIntegral = isset($cart['productInfo']['give_integral']) ? bcmul((string)$cart['cart_num'], (string)$cart['productInfo']['give_integral'], 0) : 0; $gainIntegral = bcadd((string)$gainIntegral, (string)$cartInfoGainIntegral, 0); if ($seckillId) { if (!isset($cart['product_attr_unique']) || !$cart['product_attr_unique']) continue; $type = $cart['type']; if (in_array($type, [1, 2, 3]) && ( !CacheService::checkStock($cart['product_attr_unique'], (int)$cart['cart_num'], $type) || !CacheService::popStock($cart['product_attr_unique'], (int)$cart['cart_num'], $type) ) ) { throw new ValidateException('您购买的商品库存已不足' . $cart['cart_num'] . $cart['productInfo']['unit_name']); } } } if ($collate_code_id) { $collateCodeId = (int)$deduction['collate_code_id'] ?? 0; if ($collateCodeId && $type == 10) { if ($collateCodeId != $collate_code_id) throw new ValidateException('拼单/桌码ID有误!'); $seckillId = $collate_code_id; } } /** @var StoreOrderCreateServices $orderServices */ $orderServices = app()->make(StoreOrderCreateServices::class); $key = md5(json_encode($cartIds) . uniqid() . time()); $product_type = (int)$deduction['product_type'] ?? 0; $orderInfo = [ 'uid' => $uid, 'type' => $type, 'order_id' => $orderServices->getNewOrderId(), 'real_name' => $addressInfo['real_name'] ? $addressInfo['real_name'] : $userInfo['nickname'] ?? '', 'user_phone' => $addressInfo['phone'] ? $addressInfo['phone'] : $userInfo['phone'] ?? '', 'user_address' => isset($addressInfo['addressInfo']) && $addressInfo['addressInfo'] ? $addressInfo['addressInfo'] : $addressInfo['province'] . ' ' . $addressInfo['city'] . ' ' . $addressInfo['district'] . ' ' . $addressInfo['street'] . ' ' . $addressInfo['detail'], 'cart_id' => $cartIds, 'clerk_id' => $clerk_id, 'store_id' => $storeId, 'staff_id' => $staffId, 'total_num' => $totalNum, 'total_price' => $computeData['sumPrice'] ?? $totalPrice, 'total_postage' => $computeData['pay_postage'], 'coupon_id' => $couponId, 'coupon_price' => $couponPrice, 'promotions_price' => $priceData['promotions_price'], 'pay_price' => $isPrice ? $changePrice : $computeData['payPrice'], 'pay_postage' => $computeData['pay_postage'], 'deduction_price' => $computeData['deductionPrice'], 'change_price' => $isPrice ? bcsub((string)$computeData['payPrice'], (string)$changePrice, 2) : '0.00', 'paid' => 0, 'pay_type' => $payType == self::YUE_PAY ? 'yue' : '', 'use_integral' => $useIntegral, 'gain_integral' => $gainIntegral, 'mark' => htmlspecialchars($remarks), 'product_type' => $product_type, 'activity_id' => $seckillId, 'pink_id' => 0, 'cost' => $computeData['costPrice'], 'is_channel' => 2, 'add_time' => time(), 'unique' => $key, 'shipping_type' => $shippingType, 'channel_type' => $userInfo['user_type'] ?? '', 'province' => '', 'spread_uid' => 0, 'spread_two_uid' => 0, 'promotions_give' => json_encode($promotions_give), 'give_integral' => $promotions_give['give_integral'] ?? 0, 'give_coupon' => implode(',', $promotions_give['give_coupon'] ?? []), ]; if ($product_type == 4) {//次卡商品收银台购买 $orderInfo['verify_code'] = $orderServices->getStoreCode(); $orderInfo['shipping_type'] = 2;//修改门店自提 } if ($shippingType == 2) { $orderInfo['verify_code'] = $orderServices->getStoreCode(); /** @var SystemStoreServices $storeServices */ $storeServices = app()->make(SystemStoreServices::class); $orderInfo['store_id'] = $storeServices->getStoreDisposeCache($storeId, 'id'); if (!$orderInfo['store_id']) { throw new ValidateException('暂无门店无法选择门店自提'); } } /** @var StoreOrderCartInfoServices $cartServices */ $cartServices = app()->make(StoreOrderCartInfoServices::class); $order = $orderServices->save($orderInfo); if (!$order) { throw new ValidateException('订单生成失败'); } //使用优惠券 if ($couponId) { /** @var StoreCouponUserServices $couponServices */ $couponServices = app()->make(StoreCouponUserServices::class); $res1 = $couponServices->useCoupon($couponId, (int)($userInfo['uid'] ?? 0), $cartInfo, [], $storeId); if (!$res1) { throw new ValidateException('使用优惠劵失败!'); } } //积分抵扣 $orderServices->deductIntegral($userInfo, $useIntegral, [ 'SurplusIntegral' => $computeData['surplusIntegral'], 'usedIntegral' => $computeData['usedIntegral'], 'deduction_price' => $computeData['deductionPrice'], ], (int)($userInfo['uid'] ?? 0), $key); //修改门店库存 $orderServices->decGoodsStock($cartInfo, $type, $seckillId, $storeId); //保存购物车商品信息 $cartServices->setCartInfo($order['id'], $cartInfo, $userInfo['uid'] ?? 0, $promotions_give['promotions'] ?? []); $order = $order->toArray(); if (in_array($type, [9, 10]) && $collate_code_id > 0 && $order) { //关联订单和拼单、桌码 /** @var UserCollageCodeServices $collageServices */ $collageServices = app()->make(UserCollageCodeServices::class); $collageServices->update($collate_code_id, ['oid' => $order['id'], 'status' => 2]); //清除未结算商品 /** @var UserCollagePartakeServices $partakeService */ $partakeService = app()->make(UserCollagePartakeServices::class); $partakeService->update(['collate_code_id' => $collate_code_id, 'is_settle' => 0], ['status' => 0]); } $news = false; $addressId = $type = $activity_id = 0; $delCart = true; //扣除优惠活动赠品限量 StorePromotionsJob::dispatchDo('changeGiveLimit', [$promotions_give]); $group = compact('cartInfo', 'priceData', 'addressId', 'cartIds', 'news', 'delCart', 'changePrice'); event('order.create', [$order, $group, compact('type', 'activity_id'), 0]); return $order; } /** * 收银台支付 * @param string $orderId * @param string $payType * @param string $userCode * @param string $authCode * @return array * @throws \Psr\SimpleCache\InvalidArgumentException */ public function paySuccess(string $orderId, string $payType, string $userCode, string $authCode = '') { /** @var StoreOrderSuccessServices $orderService */ $orderService = app()->make(StoreOrderSuccessServices::class); $orderInfo = $orderService->get(['order_id' => $orderId]); if (!$orderInfo) { throw new ValidateException('没有查询到订单信息'); } if ($orderInfo->paid) { throw new ValidateException('订单已支付'); } if ($orderInfo->is_del) { throw new ValidateException('订单已取消'); } switch ($payType) { case PayServices::YUE_PAY://余额支付 $is_cashier_yue_pay_verify = (int)sys_config('is_cashier_yue_pay_verify'); // 收银台余额支付是否需要验证【是/否】 if (!$orderInfo['uid']) { throw new ValidateException('余额支付用户信息不存在无法支付'); } if (!$userCode && $is_cashier_yue_pay_verify) { throw new ValidateException('缺少扫码支付参数'); } /** @var UserServices $userService */ $userService = app()->make(UserServices::class); $userInfo = $userService->getUserInfo($orderInfo->uid, ['uid', 'bar_code']); if (!$userInfo) { throw new ValidateException('余额支付用户不存在'); } if ($userInfo['bar_code'] != $userCode && $is_cashier_yue_pay_verify) { throw new ValidateException('二维码已使用或不正确,请确认后重新扫码'); } /** @var YuePayServices $payService */ $payService = app()->make(YuePayServices::class); $pay = $payService->yueOrderPay($orderInfo->toArray(), $orderInfo->uid); if ($pay['status'] === true) return ['status' => 'SUCCESS']; else if ($pay['status'] === 'pay_deficiency') { throw new ValidateException($pay['msg']); } else { return ['status' => 'ERROR', 'message' => is_array($pay) ? $pay['msg'] ?? '余额支付失败' : $pay]; } case PayServices::WEIXIN_PAY://微信支付 case PayServices::ALIAPY_PAY://支付宝支付 if (!$authCode) { throw new ValidateException('缺少支付付款二维码CODE'); } $pay = new PayServices(); $site_name = sys_config('site_name'); /** @var StoreOrderCartInfoServices $orderInfoServices */ $orderInfoServices = app()->make(StoreOrderCartInfoServices::class); $body = $orderInfoServices->getCarIdByProductTitle((int)$orderInfo['id']); $body = substrUTf8($site_name . '--' . $body, 30); try { //扫码支付 $response = $pay->setAuthCode($authCode)->pay($payType, '', $orderInfo->order_id, $orderInfo->pay_price, 'product', $body); } catch (\Throwable $e) { \think\facade\Log::error('收银端' . $payType . '扫码支付失败,原因:' . $e->getMessage()); return ['status' => 'ERROR', 'message' => '支付失败,原因:' . $e->getMessage()]; } //支付成功paid返回1 if ($response['paid']) { if (!$orderService->paySuccess($orderInfo->toArray(), $payType, ['trade_no' => $response['payInfo']['transaction_id'] ?? ''])) { return ['status' => 'ERROR', 'message' => '支付失败']; } //支付成功刪除購物車 /** @var StoreCartServices $cartServices */ $cartServices = app()->make(StoreCartServices::class); $cartServices->deleteCartStatus($orderInfo['cart_id'] ?? []); return ['status' => 'SUCCESS']; } else { if ($payType === PayServices::WEIXIN_PAY) { if (isset($response['payInfo']['err_code']) && in_array($response['payInfo']['err_code'], ['AUTH_CODE_INVALID', 'NOTENOUGH'])) { return ['status' => 'ERROR', 'message' => '支付失败']; } //微信付款码支付需要同步更改状态 $secs = 5; if (isset($order_info['payInfo']['err_code']) && $order_info['payInfo']['err_code'] === 'USERPAYING') { $secs = 10; } //放入队列执行 MicroPayOrderJob::dispatchSece($secs, [$orderInfo['order_id'], 0]); } return ['status' => 'PAY_ING', 'message' => $response['message']]; } break; case PayServices::CASH_PAY://收银台现金支付 if (!$orderService->paySuccess($orderInfo->toArray(), $payType)) { return ['status' => 'ERROR', 'message' => '支付失败']; } else { return ['status' => 'SUCCESS']; } break; default: throw new ValidateException('暂无支付方式,无法支付'); } } }