From f395a4de785bd7dcfea2f703b8e250d53e704960 Mon Sep 17 00:00:00 2001 From: weigang Date: Mon, 7 Sep 2020 17:45:04 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=9B=B8=E5=85=B3=E6=93=8D?= =?UTF-8?q?=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Constants/v3/ErrorCode.php | 24 +++ app/Constants/v3/LogLabel.php | 10 ++ app/Constants/v3/OrderState.php | 4 +- app/Controller/v3/HomeController.php | 2 +- app/Controller/v3/LocationController.php | 17 +- app/Controller/v3/OrderOfflineController.php | 2 + app/Controller/v3/OrderOnlineController.php | 90 +++++++++- app/Controller/v3/PaymentController.php | 48 ----- app/JsonRpc/OrderOnlineService.php | 87 +++++++++ app/JsonRpc/OrderOnlineServiceInterface.php | 8 + app/Model/v3/Market.php | 21 +++ app/Model/v3/OrderMain.php | 2 + app/Model/v3/ServiceReward.php | 2 + app/Model/v3/UserRelationBind.php | 2 + app/Request/v3/OrderOnlineStateRequest.php | 37 ++++ .../v3/Implementations/ActivityService.php | 7 +- .../v3/Implementations/BannerService.php | 12 +- .../v3/Implementations/CouponRecService.php | 2 +- .../v3/Implementations/CouponService.php | 112 ++++++++++++ .../Implementations/GoodsActivityService.php | 37 +++- .../Implementations/OrderOfflineService.php | 8 +- .../v3/Implementations/OrderOnlineService.php | 167 ++++++++++++------ .../SeparateAccountsService.php | 66 +++---- .../v3/Interfaces/CouponServiceInterface.php | 15 ++ .../GoodsActivityServiceInterface.php | 2 + .../OrderOnlineServiceInterface.php | 50 +++++- .../SeparateAccountsServiceInterface.php | 5 +- config/autoload/wechat.php | 4 + config/routes.php | 6 +- 29 files changed, 663 insertions(+), 186 deletions(-) delete mode 100644 app/Controller/v3/PaymentController.php create mode 100644 app/JsonRpc/OrderOnlineService.php create mode 100644 app/JsonRpc/OrderOnlineServiceInterface.php create mode 100644 app/Request/v3/OrderOnlineStateRequest.php diff --git a/app/Constants/v3/ErrorCode.php b/app/Constants/v3/ErrorCode.php index 9cdc096..faa2df5 100644 --- a/app/Constants/v3/ErrorCode.php +++ b/app/Constants/v3/ErrorCode.php @@ -53,6 +53,30 @@ class ErrorCode extends AbstractConstants */ const ORDER_NOT_AVAILABLE = 605; + /** + * 订单取消失败 + * @Message("订单取消失败") + */ + const ORDER_CANCEL_FAIL = 606; + + /** + * 订单删除失败 + * @Message("订单删除失败") + */ + const ORDER_DELETE_FAIL = 607; + + /** + * 订单申请退款失败 + * @Message("订单申请退款失败") + */ + const ORDER_APPLY_REFUND_FAIL = 608; + + /** + * 订单完成失败 + * @Message("订单完成失败") + */ + const ORDER_COMPLETE_FAIL = 609; + /************************************/ /* 支付相关 651-700 */ /************************************/ diff --git a/app/Constants/v3/LogLabel.php b/app/Constants/v3/LogLabel.php index f49eb61..c83fde0 100644 --- a/app/Constants/v3/LogLabel.php +++ b/app/Constants/v3/LogLabel.php @@ -52,6 +52,11 @@ class LogLabel extends AbstractConstants */ const ORDER_PAYMENT_LOG = 'order_payment_log'; + /** + * @Message("订单完成") + */ + const ORDER_COMPLETE_LOG = 'order_complete_log'; + /** * @Message("IOT设备绑定") */ @@ -72,4 +77,9 @@ class LogLabel extends AbstractConstants */ const SEPARATE_ACCOUNTS_LOG = 'separate_accounts_log'; + /** + * @Message("优惠券退还") + */ + const COUPON_REFUND_LOG = 'coupon_refund_log'; + } diff --git a/app/Constants/v3/OrderState.php b/app/Constants/v3/OrderState.php index cc0fb41..f6848f5 100644 --- a/app/Constants/v3/OrderState.php +++ b/app/Constants/v3/OrderState.php @@ -68,11 +68,13 @@ class OrderState extends AbstractConstants /** * @Message("订单完成") */ - const FINISH = [self::COMPLETED, self::EVALUATED]; + const FINISH = [self::COMPLETED, self::EVALUATED, self::CANCELED]; /** * @Message("售后/退款") */ const REFUND = [self::REFUNDING, self::REFUNDED, self::REFUND_REFUSE]; + const CAN_DEL = [self::COMPLETED, self::EVALUATED, self::CANCELED, self::REFUNDED, self::REFUND_REFUSE]; + } \ No newline at end of file diff --git a/app/Controller/v3/HomeController.php b/app/Controller/v3/HomeController.php index 04de8ca..062b63d 100644 --- a/app/Controller/v3/HomeController.php +++ b/app/Controller/v3/HomeController.php @@ -94,7 +94,7 @@ class HomeController extends BaseController public function appletIndex() { - $marketId = $this->request->input('market_id', 0); + $marketId = $this->request->input('market_id', -1); $banners = $this->bannerService->all(Banner::TYPE_APPLET_INDEX, $marketId); $categories = $this->categoryService->allForAppletIndex(); $activity = $this->activityService->allForAppletIndex(env('APPLET_INDEX_ACTIVITY_TYPE'), $marketId); diff --git a/app/Controller/v3/LocationController.php b/app/Controller/v3/LocationController.php index 8fbffae..04d043b 100644 --- a/app/Controller/v3/LocationController.php +++ b/app/Controller/v3/LocationController.php @@ -3,6 +3,7 @@ namespace App\Controller\v3; use App\Controller\BaseController; +use App\Model\v3\Market; use App\Service\v3\Interfaces\LocationServiceInterface; use Hyperf\Di\Annotation\Inject; @@ -27,21 +28,7 @@ class LocationController extends BaseController */ public function getNearestMarket() { - return $this->success([ - 'market' => [ - 'id' => 1, - 'name' => '海尔青啤', - 'province_id' => 1, - 'province_name' => '广西', - 'city_id' => 2, - 'city_name' => '南宁市', - 'area_id' => 3, - 'area_name' => '良庆区', - 'address' => '海尔青啤广场', - 'lng' => '108.383566', - 'lat' => '22.759946', - ] - ]); + return $this->success(Market::query()->find(1)); } public function getMarketListByLocation() diff --git a/app/Controller/v3/OrderOfflineController.php b/app/Controller/v3/OrderOfflineController.php index 05539aa..5951e52 100644 --- a/app/Controller/v3/OrderOfflineController.php +++ b/app/Controller/v3/OrderOfflineController.php @@ -9,6 +9,7 @@ use App\Service\v3\Interfaces\OrderOfflineServiceInterface; use App\Service\v3\Interfaces\StoreServiceInterface; use Hyperf\Validation\ValidationException; use Hyperf\Di\Annotation\Inject; +use Psr\Http\Message\ResponseInterface; class OrderOfflineController extends BaseController { @@ -51,6 +52,7 @@ class OrderOfflineController extends BaseController * 1、用户id、去商户id下支付、支付的金额 * 2、下单同时支付,下发支付参数 * @param OrderOfflineRequest $request + * @return ResponseInterface */ public function add(OrderOfflineRequest $request) { diff --git a/app/Controller/v3/OrderOnlineController.php b/app/Controller/v3/OrderOnlineController.php index a2cd5e7..b740c7b 100644 --- a/app/Controller/v3/OrderOnlineController.php +++ b/app/Controller/v3/OrderOnlineController.php @@ -3,12 +3,19 @@ namespace App\Controller\v3; use App\Constants\v3\ErrorCode; +use App\Constants\v3\LogLabel; +use App\Constants\v3\OrderState; use App\Controller\BaseController; use App\Exception\ErrorCodeException; +use App\Model\v3\OrderMain; use App\Request\v3\OrderOnlineDetailRequest; use App\Request\v3\OrderOnlineRequest; +use App\Request\v3\OrderOnlineStateRequest; +use App\Service\v3\Implementations\PaymentService; use App\Service\v3\Interfaces\CouponRecServiceInterface; +use App\Service\v3\Interfaces\SeparateAccountsServiceInterface; use App\Service\v3\Interfaces\ShopCartServiceInterface; +use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; use App\Service\v3\Interfaces\OrderOnlineServiceInterface; use App\Service\v3\Interfaces\UserBindTelServiceInterface; @@ -46,6 +53,12 @@ class OrderOnlineController extends BaseController */ protected $shopCartService; + /** + * @Inject + * @var SeparateAccountsServiceInterface + */ + protected $separateAccountsService; + /* * 如果没有绑手机号去绑定页面 * 收货地址接口 @@ -110,6 +123,7 @@ class OrderOnlineController extends BaseController // 下单 $params = $request->validated(); + $couponIds = isset($params['coupon_ids'])&&$params['coupon_ids'] ? explode(',', $params['coupon_ids']) : []; $data = $this->orderOnlineService->do( $params['market_id'], $params['user_id'], @@ -118,10 +132,84 @@ class OrderOnlineController extends BaseController $params['total_money'], $params['delivery_time_note'], $params['service_money'], - explode(',', $params['coupon_ids']), + $couponIds, $params['plat'] ); return $this->success(['data' => $data]); } + + /** + * 待支付订单重新发起支付 + * 1、用户id、订单id + * 2、发起支付 + * @param OrderOnlineStateRequest $request + * @return ResponseInterface + */ + public function pay(OrderOnlineStateRequest $request) + { + $params = $request->validated(); + $data = $this->orderOnlineService->doPay($params['order_id'], $params['user_id']); + return $this->success(['data' => $data]); + } + + /** + * 取消订单 + * @param OrderOnlineStateRequest $request + * @return ResponseInterface + */ + public function cancel(OrderOnlineStateRequest $request) + { + $params = $request->validated(); + $this->orderOnlineService->undo($params['order_id'], $params['user_id']); + return $this->success([]); + } + + /** + * 删除订单 + * @param OrderOnlineStateRequest $request + * @return ResponseInterface + */ + public function del(OrderOnlineStateRequest $request) + { + $params = $request->validated(); + $this->orderOnlineService->doDel($params['order_id'], $params['user_id']); + return $this->success([]); + } + + /** + * 申请退款 + * @param OrderOnlineStateRequest $request + * @return ResponseInterface + */ + public function applyRefund(OrderOnlineStateRequest $request) + { + $params = $request->validated(); + $this->orderOnlineService->doApplyRefund($params['order_id'], $params['user_id']); + return $this->success([]); + } + + /** + * 完成订单 + * @param OrderOnlineStateRequest $request + * @return ResponseInterface + */ + public function complete(OrderOnlineStateRequest $request) + { + Db::beginTransaction(); + try { + + $params = $request->validated(); + $this->orderOnlineService->doComplete($params['order_id'], $params['user_id']); + $this->separateAccountsService->orderOnlineCompleted($params['order_id'], $params['user_id']); + + Db::commit(); + return $this->success([]); + } catch (\Exception $e) { + + Db::rollBack(); + $this->log->event(LogLabel::ORDER_COMPLETE_LOG, ['exception' => $e->getMessage()]); + throw new ErrorCodeException(ErrorCode::ORDER_COMPLETE_FAIL, $e->getMessage()); + } + } } \ No newline at end of file diff --git a/app/Controller/v3/PaymentController.php b/app/Controller/v3/PaymentController.php deleted file mode 100644 index 549b60b..0000000 --- a/app/Controller/v3/PaymentController.php +++ /dev/null @@ -1,48 +0,0 @@ -validationFactory->make( - $this->request->all(), - [ - 'global_order_id' => 'required|nonempty', - 'user_id' => 'required|nonempty', - ], - [ - 'global_order_id.*' => '订单号错误' - ] - ); - - if ($validator->fails()) { - throw new ValidationException($validator); - } - - $params = $validator->validated(); - $orderMain = OrderMain::query()->select('global_order_id', 'money', 'user_id') - ->where(['global_order_id' => $params['global_order_id']])->first(); - $parameters = $this->paymentService->do($orderMain->global_order_id, $orderMain->money, $orderMain->user_id); - - return $this->success(['parameters' => $parameters]); - } -} \ No newline at end of file diff --git a/app/JsonRpc/OrderOnlineService.php b/app/JsonRpc/OrderOnlineService.php new file mode 100644 index 0000000..b7d0360 --- /dev/null +++ b/app/JsonRpc/OrderOnlineService.php @@ -0,0 +1,87 @@ +orderOnlineService->doComplete($orderMainId, $userId); + $this->separateAccountsService->orderOnlineCompleted($orderMainId, $userId); + + Db::commit(); + return [ + "status" => 200, + "code" => 0, + "result" => [], + "message" => '调用成功' + ]; + } catch (\Exception $e) { + + Db::rollBack(); + $this->log->event(LogLabel::ORDER_COMPLETE_LOG, ['exception' => $e->getMessage()]); + throw new ErrorCodeException(ErrorCode::ORDER_COMPLETE_FAIL, $e->getMessage()); + } + + } + + /** + * 线上订单退款 + * 申请退款 state = 8 + * 退款成功 state = 9 + */ + public function onlineRefund($global_order_id){ + $result = [ + "status" => 200, + "code" => ErrorCode::ORDER_FAILURE, + "result" => [], + "message" => '' + ]; + + $res = $this->orderOnlineService->onlineRefund($global_order_id); + if($res['code'] > 0){ + $result['result'] = $res; + $result['message'] = '退款失败'; + }else{ + $result['code'] = 0; + $result['result'] = $res; + $result['message'] = '退款成功'; + }; + + return $result; + } +} \ No newline at end of file diff --git a/app/JsonRpc/OrderOnlineServiceInterface.php b/app/JsonRpc/OrderOnlineServiceInterface.php new file mode 100644 index 0000000..5f26e43 --- /dev/null +++ b/app/JsonRpc/OrderOnlineServiceInterface.php @@ -0,0 +1,8 @@ +find($this->attributes['province_id'])->value('name'); + } + + public function getCityNameAttribute() + { + return Area::query()->find($this->attributes['city_id'])->value('name'); + } + + public function getRegionNameAttribute() + { + return Area::query()->find($this->attributes['region_id'])->value('name'); + } + public function stores() { return $this->hasMany(Store::class,'market_id','id'); diff --git a/app/Model/v3/OrderMain.php b/app/Model/v3/OrderMain.php index d7de827..9d4f06b 100644 --- a/app/Model/v3/OrderMain.php +++ b/app/Model/v3/OrderMain.php @@ -6,9 +6,11 @@ use App\Constants\v3\OrderState; use App\Constants\v3\Payment; use App\Constants\v3\Shipping; use App\Model\Model; +use Hyperf\Database\Model\SoftDeletes; class OrderMain extends Model { + use SoftDeletes; protected $table = 'lanzu_order_main'; protected $fillable = [ diff --git a/app/Model/v3/ServiceReward.php b/app/Model/v3/ServiceReward.php index 3f8647c..a003ec0 100644 --- a/app/Model/v3/ServiceReward.php +++ b/app/Model/v3/ServiceReward.php @@ -3,6 +3,8 @@ declare (strict_types=1); namespace App\Model\v3; +use App\Model\Model; + class ServiceReward extends Model { /** diff --git a/app/Model/v3/UserRelationBind.php b/app/Model/v3/UserRelationBind.php index 772c681..3dd22e3 100644 --- a/app/Model/v3/UserRelationBind.php +++ b/app/Model/v3/UserRelationBind.php @@ -3,6 +3,8 @@ declare (strict_types=1); namespace App\Model\v3; +use App\Model\Model; + /** */ class UserRelationBind extends Model diff --git a/app/Request/v3/OrderOnlineStateRequest.php b/app/Request/v3/OrderOnlineStateRequest.php new file mode 100644 index 0000000..523fb40 --- /dev/null +++ b/app/Request/v3/OrderOnlineStateRequest.php @@ -0,0 +1,37 @@ + 'required|nonempty|integer', + 'user_id' => 'required|nonempty|integer', + ]; + } + + /** + * @return array + */ + public function messages(): array + { + return [ + '*.*' => ':attribute无效', + ]; + } + + public function attributes(): array + { + return parent::attributes(); + } +} diff --git a/app/Service/v3/Implementations/ActivityService.php b/app/Service/v3/Implementations/ActivityService.php index 76a14f4..15cbc6e 100644 --- a/app/Service/v3/Implementations/ActivityService.php +++ b/app/Service/v3/Implementations/ActivityService.php @@ -28,8 +28,11 @@ class ActivityService implements ActivityServiceInterface { $builder = GoodsActivity::query() ->with(['store']) - ->where(['type' => $type]) - ->whereIn('market_id', [0,$marketId]); + ->where(['type' => $type]); + + if ($marketId != -1) { + $builder = $builder->whereJsonContains('market_ids', [(string)$marketId]); + } return $builder->get()->toArray(); } diff --git a/app/Service/v3/Implementations/BannerService.php b/app/Service/v3/Implementations/BannerService.php index c686de4..05d30bd 100644 --- a/app/Service/v3/Implementations/BannerService.php +++ b/app/Service/v3/Implementations/BannerService.php @@ -9,9 +9,13 @@ class BannerService implements BannerServiceInterface { public function all($type, $marketId) { - return Banner::query() - ->where(['type' => $type]) - ->whereJsonContains('market_ids', [(string)$marketId]) - ->get()->toArray(); + $builder = Banner::query() + ->where(['type' => $type]); + + if ($marketId != -1) { + $builder = $builder->whereJsonContains('market_ids', [(string)$marketId]); + } + + return $builder->get()->toArray(); } } \ No newline at end of file diff --git a/app/Service/v3/Implementations/CouponRecService.php b/app/Service/v3/Implementations/CouponRecService.php index 02f9d7d..eb4c764 100644 --- a/app/Service/v3/Implementations/CouponRecService.php +++ b/app/Service/v3/Implementations/CouponRecService.php @@ -56,7 +56,7 @@ class CouponRecService implements CouponRecServiceInterface } if (!empty($storeTypeIds)) { - $builder->whereJsonContains('coupon.storetype_ids', $storeTypeIds); + $builder->whereJsonContains('coupon.category_ids', $storeTypeIds); } $builder->where(['receive.user_id' => $userId]) diff --git a/app/Service/v3/Implementations/CouponService.php b/app/Service/v3/Implementations/CouponService.php index 950937b..5071541 100644 --- a/app/Service/v3/Implementations/CouponService.php +++ b/app/Service/v3/Implementations/CouponService.php @@ -2,7 +2,14 @@ namespace App\Service\v3\Implementations; +use App\Constants\v3\ErrorCode; +use App\Constants\v3\LogLabel; +use App\Exception\ErrorCodeException; +use App\Model\v3\CouponRec; +use App\Model\v3\CouponUse; +use App\Model\v3\OrderMain; use App\Service\v3\Interfaces\CouponServiceInterface; +use Hyperf\DbConnection\Db; use Hyperf\Redis\Redis; use Hyperf\Utils\ApplicationContext; @@ -55,4 +62,109 @@ class CouponService implements CouponServiceInterface $expireRes = $redis->expire('coupon_' . date('Ymd') . '_used_' . $userId, strtotime(date('Y-m-d') . ' 23:59:59') - time()); return $setRes && $expireRes; } + + public function orderUseCoupons($orderMainId, $couponRecs) + { + Db::beginTransaction(); + try { + if (is_array($couponRecs)&&!empty($couponRecs)) { + # 使用记录、更新当前优惠券 + foreach ($couponRecs as $key => &$coupon) { + + $couponUse = [ + 'user_id' => $coupon['user_id'], + 'user_receive_id' => $coupon['id'], + 'coupon_id' => $coupon['coupon_id'], + 'order_main_id' => $orderMainId, + 'use_time' => time(), + 'return_time' => 0, + 'number' => 1, + 'status' => 1, + 'update_time' => 0, + ]; + + $insertRes = CouponUse::query()->insert($couponUse); + if ($insertRes) { + $status = 0; + $numberRemain = $coupon['number_remain'] - 1; + if ($numberRemain == 0) { + $status = 2; + } elseif ($numberRemain > 0 && $numberRemain < $coupon['number']) { + $status = 1; + } elseif ($numberRemain == $coupon['number']) { + $status = 0; + } + + $upRes = CouponRec::query()->where(['id' => $coupon['id']]) + ->update(['number_remain' => $numberRemain, 'status' => $status]); + if (!$upRes) { + Db::rollBack(); + throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); + } + // 缓存使用记录 + $usedRes = $this->cacheTodayCouponUsed($coupon['user_id'], $coupon['coupon_id'], $coupon['id']); + if (!$usedRes) { + Db::rollBack(); + throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); + } + } else { + Db::rollBack(); + throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); + } + + } + } + + Db::commit(); + } catch (\Exception $e) { + Db::rollBack(); + throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE, $e->getMessage()); + } + + } + + /** + * 退还优惠券,订单取消,申请退款成功时 + * 先查询是否正常使用优惠券 + * 修改状态,退还领取记录库存,删除ssdb缓存 + * @param $orderMainId + * @return bool + */ + public function orderRefundCoupons($orderMainId) + { + $currentTime = time(); + Db::beginTransaction(); + try { + $couponUses = CouponUse::query() + ->where('order_main_id', $orderMainId) + ->where('status', 1) + ->get(); + if (!empty($couponUses)) { + foreach ($couponUses as $use) { + $use->status = 1; + $use->return_time = $currentTime; + $use->update_time = $currentTime; + $res = $use->save(); + $couponReceive = CouponRec::query() + ->where('id', $use->user_receive_id) + ->whereRaw('number >= number_remain+' . $use->number) + ->update([ + 'number_remain' => Db::raw('number_remain+' . $use->number), + 'status' => Db::raw('IF(number=number_remain, 0,1)'), 'update_time' => $currentTime + ]); + + if ($res && $couponReceive) { + $redis = ApplicationContext::getContainer()->get(Redis::class); + $clearUseRedis = $redis->sRem('coupon_' . date('Ymd') . '_used_' . $use->user_id, $use->coupon_id); + } + } + } + Db::commit(); + return true; + } catch (\Exception $e) { + $this->log->event(LogLabel::COUPON_REFUND_LOG, ['msg' => '订单取消/退款退还优惠券', 'exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + } } \ No newline at end of file diff --git a/app/Service/v3/Implementations/GoodsActivityService.php b/app/Service/v3/Implementations/GoodsActivityService.php index 884dfa7..09f7df8 100644 --- a/app/Service/v3/Implementations/GoodsActivityService.php +++ b/app/Service/v3/Implementations/GoodsActivityService.php @@ -31,7 +31,7 @@ class GoodsActivityService implements GoodsActivityServiceInterface } // 商户歇业 - if($goods->store->is_rest != Store::IS_OPEN_YES){ + if($goods->store->is_rest == 1){ return ErrorCode::GOODS_ACTIVITY_ON_SALE_NO; } @@ -46,13 +46,13 @@ class GoodsActivityService implements GoodsActivityServiceInterface } // 是否超过限购数量 - if ($goods->restrict_num > $num) { + if ($goods->restrict_num < $num) { return ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT; } // 是否已经购买过(某个时间段内,时间段有商品的限制) $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); - $hasBuy = $ssdb->exec('get', SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goodsId); + $hasBuy = $ssdb->exec('get', SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goodsId); if ($hasBuy && $hasBuy >= $goods->time_limit_num) { return ErrorCode::GOODS_ACTIVITY_BUY; } @@ -80,17 +80,19 @@ class GoodsActivityService implements GoodsActivityServiceInterface public function cacheRecord($goodsId, $num, $userId) { - $goods = GoodsActivity::query()->select('time_limit_days', 'time_limit_num') + $goods = GoodsActivity::query() ->where('id', $goodsId) ->first(); - $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goodsId; + $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goodsId; $expireTime = 0; - if ($goods->time_limit_days <= 1) { + if ($goods->time_limit_days >= 1) { $expireTime += strtotime(date('Y-m-d 23:59:59')) - time(); + var_dump('ex1', $expireTime); } - $expireTime += ($goods->time_limit_days-1) *86400; + $expireTime += ($goods->time_limit_days-1) * 86400; + var_dump('ex2', $expireTime); $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); @@ -103,6 +105,27 @@ class GoodsActivityService implements GoodsActivityServiceInterface } + public function clearCacheRecord($goodsId, $num, $userId) + { + $goods = GoodsActivity::query() + ->where('id', $goodsId) + ->first(); + var_dump('$goods', $goods, $goodsId); + if (empty($goods)) { + return true; + } + $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goodsId; + var_dump('ssdbkey', $ssdbKey); + + $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); + + if (!$ssdb->exec('exists', $ssdbKey)) { + } else { + $res = $ssdb->exec('incr', $ssdbKey, -1*$num); + var_dump('res', $res, -1*$num); + } + } + /** * 统计订单中活动商品的数量,并校验 * @param $orderGoods diff --git a/app/Service/v3/Implementations/OrderOfflineService.php b/app/Service/v3/Implementations/OrderOfflineService.php index 908268f..8ebdaf3 100644 --- a/app/Service/v3/Implementations/OrderOfflineService.php +++ b/app/Service/v3/Implementations/OrderOfflineService.php @@ -57,7 +57,7 @@ class OrderOfflineService implements OrderOfflineServiceInterface 'delivery_time_note' => '' ]; - $orderMain = OrderMain::create($dataMain); + $orderMain = OrderMain::query()->create($dataMain); $orderMainId = $orderMain->id; // 子订单数据 @@ -70,15 +70,15 @@ class OrderOfflineService implements OrderOfflineServiceInterface 'note' => '' ]; - $orderChild = Order::create($dataChildren); + $orderChild = Order::query()->create($dataChildren); $orderChildId = $orderChild->id; Db::commit(); // 支付 - return $this->paymentService->do($globalOrderId, $money, $userId, config('site_host') . '/v3/wechat/notify/offline'); + return $this->paymentService->do($globalOrderId, $money, $userId, config('wechat.notify_url.offline')); } catch (\Exception $e) { Db::rollBack(); - $this->log->event(LogLabel::ORDER_ONLINE_LOG, ['exception_msg' => $e->getMessage()]); + $this->log->event(LogLabel::ORDER_OFFLINE_LOG, ['exception_msg' => $e->getMessage()]); throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL); } } diff --git a/app/Service/v3/Implementations/OrderOnlineService.php b/app/Service/v3/Implementations/OrderOnlineService.php index 7ef305c..8c36c40 100644 --- a/app/Service/v3/Implementations/OrderOnlineService.php +++ b/app/Service/v3/Implementations/OrderOnlineService.php @@ -29,6 +29,8 @@ use App\Service\v3\Interfaces\GoodsActivityServiceInterface; use App\Service\v3\Interfaces\GoodsServiceInterface; use App\Service\v3\Interfaces\PaymentServiceInterface; use App\TaskWorker\SSDBTask; +use Exception; +use Hyperf\Database\Model\Model; use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; use App\Service\v3\Interfaces\OrderOnlineServiceInterface; @@ -142,13 +144,13 @@ class OrderOnlineService implements OrderOnlineServiceInterface $goods = Goods::query()->lockForUpdate()->find($cart->goods_id); $check = $this->goodsService->check($goods->id, $cart->num); if (true !== $check) { - // throw new ErrorCodeException($check, '[商品失效1]'.$cart->goods_id); + throw new ErrorCodeException($check, '[商品失效1]'.$cart->goods_id); } } elseif ($cart->activity_type == 2) { $goods = GoodsActivity::query()->lockForUpdate()->find($cart->goods_id); $check = $this->goodsActivityService->check($goods->id, $cart->num, $userId); if (true !== $check) { - // throw new ErrorCodeException($check, '[商品失效2]'.$cart->goods_id); + throw new ErrorCodeException($check, '[商品失效2]'.$cart->goods_id); } // 活动商品不可用优惠券 @@ -314,71 +316,70 @@ class OrderOnlineService implements OrderOnlineServiceInterface } // 优惠券红包使用记录 - if (is_array($couponRec)&&!empty($couponRec)) { - # 使用记录、更新当前优惠券 - foreach ($couponRec as $key => &$coupon) { - - $couponUse = [ - 'user_id' => $coupon['user_id'], - 'user_receive_id' => $coupon['id'], - 'coupon_id' => $coupon['coupon_id'], - 'order_main_id' => $orderMainId, - 'use_time' => $currentTime, - 'return_time' => 0, - 'number' => 1, - 'status' => 1, - 'update_time' => 0, - ]; - - $insertRes = CouponUse::query()->insert($couponUse); - if ($insertRes) { - $numberRemain = $coupon['number_remain'] - 1; - if ($numberRemain == 0) { - $status = 2; - } elseif ($numberRemain > 0 && $numberRemain < $coupon['number']) { - $status = 1; - } elseif ($numberRemain == $coupon['number']) { - $status = 0; - } - - $upRes = CouponRec::query()->where(['id' => $coupon['id']])->update(['number_remain' => $numberRemain, 'status' => $status]); - if (!$upRes) { - Db::rollBack(); - throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); - } - // 缓存使用记录 - $usedRes = $this->couponService->cacheTodayCouponUsed($coupon['user_id'], $coupon['coupon_id'], $coupon['id']); - if (!$usedRes) { - Db::rollBack(); - throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); - } - } else { - Db::rollBack(); - throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); - } - - } - } + $this->couponService->orderUseCoupons($orderMainId, $couponRec); Db::commit(); // 支付 - return $this->paymentService->do($globalOrderId, $totalAmount, $userId, config('site_host') . '/v3/wechat/notify/online'); - } catch (\Exception $e) { + return $this->paymentService->do($globalOrderId, $totalAmount, $userId, config('wechat.notify_url.online')); + } catch (Exception $e) { Db::rollBack(); $this->log->event(LogLabel::ORDER_ONLINE_LOG, ['exception_msg' => $e->getMessage()]); - throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL); + throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL, $e->getMessage()); } } - public function check() + public function check($orderMainId, $userId, $state): Model { - // TODO: Implement check() method. + $builder = OrderMain::query() + ->where(['id' => $orderMainId, 'user_id' => $userId]); + + if (is_array($state)) { + $builder = $builder->whereIn('state', $state); + } else { + $builder = $builder->where(['state' => $state]); + } + $orderMain = $builder->first(); + if (empty($orderMain)) { + throw new ErrorCodeException(ErrorCode::ORDER_NOT_AVAILABLE); + } + + return $orderMain; } - public function undo() + /** + * @inheritDoc + */ + public function undo($orderMainId, $userId) { - // TODO: Implement undo() method. + Db::beginTransaction(); + try { + // 订单待支付 + $orderMain = $this->check($orderMainId, $userId, OrderState::UNPAID); + $orderMain->state = OrderState::CANCELED; + if (!$orderMain->save()) { + throw new ErrorCodeException(ErrorCode::ORDER_NOT_AVAILABLE); + } + + // 退还优惠券 + $this->couponService->orderRefundCoupons($orderMainId); + + // 撤销活动商品购买记录 + $orders = Order::query()->where(['order_main_id' => $orderMainId])->get()->toArray(); + $orderGoods = OrderGoods::query() + ->where('activity_type', 2) + ->whereIn('order_id', array_values(array_column($orders, 'id'))) + ->get(); + foreach ($orderGoods as $key => &$goods) { + $this->goodsActivityService->clearCacheRecord($goods->goods_id, $goods->number, $orderMain->user_id); + } + + Db::commit(); + return true; + } catch (Exception $e) { + Db::rollBack(); + throw new ErrorCodeException(ErrorCode::ORDER_CANCEL_FAIL, $e->getMessage()); + } } public function detailByUser($orderMainId, $userId) @@ -476,11 +477,67 @@ class OrderOnlineService implements OrderOnlineServiceInterface Db::commit(); return true; - } catch (\Exception $e) { + } catch (Exception $e) { $this->log->event(LogLabel::ORDER_ONLINE_PAID_LOG, ['exception' => $e->getMessage()]); Db::rollBack(); return false; } } + + /** + * @inheritDoc + */ + public function doPay($orderMainId, $userId) + { + // 订单待支付 + $orderMain = $this->check($orderMainId, $userId, OrderState::UNPAID); + return $this->paymentService->do( + $orderMain->global_order_id, + $orderMain->money, + $orderMain->user_id, + config('wechat.notify_url.online') + ); + } + + /** + * @inheritDoc + * @throws Exception + */ + public function doDel($orderMainId, $userId) + { + // 订单完成 + $orderMain = $this->check($orderMainId, $userId, OrderState::CAN_DEL); + if (!$orderMain->delete()) { + throw new ErrorCodeException(ErrorCode::ORDER_DELETE_FAIL); + } + return true; + } + + /** + * @inheritDoc + */ + public function doApplyRefund($orderMainId, $userId) + { + // 未接单 + $orderMain = $this->check($orderMainId, $userId, OrderState::PAID); + $orderMain->state = OrderState::REFUNDING; + if (!$orderMain->save()) { + throw new ErrorCodeException(ErrorCode::ORDER_APPLY_REFUND_FAIL); + } + return true; + } + + /** + * @inheritDoc + */ + public function doComplete($orderMainId, $userId) + { + $orderMain = $this->check($orderMainId, $userId, OrderState::RECEIVING); + $orderMain->state = OrderState::COMPLETED; + if (!$orderMain->save()) { + throw new ErrorCodeException(ErrorCode::ORDER_COMPLETE_FAIL); + } + return true; + } } \ No newline at end of file diff --git a/app/Service/v3/Implementations/SeparateAccountsService.php b/app/Service/v3/Implementations/SeparateAccountsService.php index 20ea856..3cc9f7b 100644 --- a/app/Service/v3/Implementations/SeparateAccountsService.php +++ b/app/Service/v3/Implementations/SeparateAccountsService.php @@ -4,6 +4,7 @@ namespace App\Service\v3\Implementations; use App\Commons\Log; use App\Constants\v3\LogLabel; +use App\Constants\v3\OrderState; use App\Model\v3\FinancialRecord; use App\Model\v3\Order; use App\Model\v3\OrderMain; @@ -16,6 +17,7 @@ use App\Model\v3\UserRelationBind; use App\Model\v3\User; use App\Service\v3\Interfaces\FinancialRecordServiceInterface; use App\Service\v3\Interfaces\MiniprogramServiceInterface; +use App\Service\v3\Interfaces\OrderOnlineServiceInterface; use App\Service\v3\Interfaces\SeparateAccountsServiceInterface; use App\Service\v3\Interfaces\UserServiceInterface; use Hyperf\DbConnection\Db; @@ -47,6 +49,12 @@ class SeparateAccountsService implements SeparateAccountsServiceInterface */ protected $miniprogramService; + /** + * @Inject + * @var OrderOnlineServiceInterface + */ + protected $orderOnlineService; + /** * @inheritDoc */ @@ -75,18 +83,11 @@ class SeparateAccountsService implements SeparateAccountsServiceInterface /** * @inheritDoc */ - public function orderOnlineCompleted($global_order_id) + public function orderOnlineCompleted($orderMainId, $userId) { // 线上订单完成(用户点击确认收货完成/管理后台点击完成/配送员点击完成/自动收货等),进行相关分账 // 订单 - $orderMain = OrderMain::query() - ->where(['global_order_id' => $global_order_id]) - ->whereIn('state', [OrderMain::ORDER_STATE_COMPLETE,OrderMain::ORDER_STATE_EVALUATED,OrderMain::ORDER_STATE_UNREFUND]) - ->first(); - - if (empty($orderMain)) { - return false; - } + $orderMain = $this->orderOnlineService->check($orderMainId, $userId,OrderState::FINISH); $currentTime = time(); Db::beginTransaction(); @@ -94,35 +95,14 @@ class SeparateAccountsService implements SeparateAccountsServiceInterface // =======商户订单收入流水 / Start======= // 查询子订单 - $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) + $orders = Order::query() ->where(['order_main_id' => $orderMain->id]) ->get()->toArray(); + // 新商户流水 foreach ($orders as $key => &$order) { - - // 商户 - $store = Store::find($order['store_id']); - - // 旧商户流水基础数据 TODO 直接移除或后续考虑移除 - $storeAccountBase = [ - 'user_id' => $order['user_id'], - 'order_id' => $order['id'], - 'store_id' => $order['store_id'], - 'type' => 1, - 'time' => date('Y-m-d H:i:s', $currentTime), - 'add_time' => $currentTime, - ]; - - // 旧商户流水 TODO 直接移除或后续考虑移除 - $storeAccount = [ - 'money' => $order['money'], - 'note' => '线上订单', - 'category' => 1, - ]; - StoreAccount::query()->insert(array_merge($storeAccountBase, $storeAccount)); - - // 新商户流水 - $this->financialRecordService->storeByOLOrderComp($store->user_id, $global_order_id ,$order['money']); + $store = Store::query()->find($order['store_id']); + $this->financialRecordService->storeByOLOrderComp($store->user_id, $orderMain->global_order_id ,$order['money']); } // =======商户订单收入流水 / End======= @@ -138,25 +118,29 @@ class SeparateAccountsService implements SeparateAccountsServiceInterface ->first(); if ($communityBind) { - // 奖励/分账金额 $award = ServiceReward::query()->where(['type' => ServiceReward::TYPE_COMMUNITY])->first(); if (empty($award)) { Db::rollBack(); return false; } - $award = $award->set_reward; - // 平台新用户 if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->id)) { - $this->financialRecordService->communityAwardByPlatNewUser($communityBind->source_id, $global_order_id, $award['new_user_reward']); - $this->financialRecordService->communityAwardByPlatNewUserFirstOLOrder($communityBind->source_id, $global_order_id, $award['first_reward']); + $this->financialRecordService->communityAwardByPlatNewUser( + $communityBind->source_id, + $orderMain->global_order_id, + $award['new_user_reward'] + ); + $this->financialRecordService->communityAwardByPlatNewUserFirstOLOrder( + $communityBind->source_id, + $orderMain->global_order_id, + $award['first_reward'] + ); } - // 账单分成 $money = bcmul($orderMain->money, bcdiv($award['flow_reward'], 100, 6), 2); - $this->financialRecordService->communitySeparateAccountsByOrderComp($communityBind->source_id, $global_order_id, $money); + $this->financialRecordService->communitySeparateAccountsByOrderComp($communityBind->source_id, $orderMain->global_order_id, $money); } // =======社区服务点分账 / End======= diff --git a/app/Service/v3/Interfaces/CouponServiceInterface.php b/app/Service/v3/Interfaces/CouponServiceInterface.php index cd42129..c44e41e 100644 --- a/app/Service/v3/Interfaces/CouponServiceInterface.php +++ b/app/Service/v3/Interfaces/CouponServiceInterface.php @@ -28,4 +28,19 @@ interface CouponServiceInterface * @return mixed */ public function countAvailableByUser($userId); + + /** + * 订单使用优惠券 + * @param $orderMainId + * @param $couponRecs + * @return mixed + */ + public function orderUseCoupons($orderMainId, $couponRecs); + + /** + * 订单退还优惠券 + * @param $orderMainId + * @return mixed + */ + public function orderRefundCoupons($orderMainId); } \ No newline at end of file diff --git a/app/Service/v3/Interfaces/GoodsActivityServiceInterface.php b/app/Service/v3/Interfaces/GoodsActivityServiceInterface.php index 13b6719..2ef9218 100644 --- a/app/Service/v3/Interfaces/GoodsActivityServiceInterface.php +++ b/app/Service/v3/Interfaces/GoodsActivityServiceInterface.php @@ -9,5 +9,7 @@ interface GoodsActivityServiceInterface public function undo(); public function getBanner($goodsId); public function detail($goodsId); + public function cacheRecord($goodsId, $num, $userId); + public function clearCacheRecord($goodsId, $num, $userId); public function checkOrderActivityCount($orderGoods, $limitNum=1); } \ No newline at end of file diff --git a/app/Service/v3/Interfaces/OrderOnlineServiceInterface.php b/app/Service/v3/Interfaces/OrderOnlineServiceInterface.php index 968c88b..e17c3d1 100644 --- a/app/Service/v3/Interfaces/OrderOnlineServiceInterface.php +++ b/app/Service/v3/Interfaces/OrderOnlineServiceInterface.php @@ -2,20 +2,64 @@ namespace App\Service\v3\Interfaces; +use Hyperf\Database\Model\Model; + interface OrderOnlineServiceInterface { public function do($marketId, $userId, $userAddrId, $storeList, $totalMoney, $deliveryTimeNote='尽快送达', $serviceMoney, $receiveCouponIds=null, $plat=''); - public function check(); + /** + * 订单是否存在,有效 + * @param $orderMainId + * @param $userId + * @param $state + * @return mixed + */ + public function check($orderMainId, $userId, $state): Model; - public function undo(); + /** + * 取消订单 + * @param $orderMainId + * @param $userId + * @return mixed + */ + public function undo($orderMainId, $userId); public function detailByUser($orderMainId, $userId); /** - * 线上订单支付完成(支付成功) + * 线上订单支付完成(支付成功)后续处理 * @param $orderMainId * @return mixed */ public function doByPaid($orderMainId); + + /** + * 线上订单支付 + * @param $orderMainId + * @param $userId + */ + public function doPay($orderMainId, $userId); + + /** + * 删除订单 + * @param $orderMainId + * @param $userId + */ + public function doDel($orderMainId, $userId); + + /** + * 申请退款 + * @param $orderMainId + * @param $userId + */ + public function doApplyRefund($orderMainId, $userId); + + /** + * 确认收货等完成订单 + * @param $orderMainId + * @param $userId + * @return mixed + */ + public function doComplete($orderMainId, $userId); } \ No newline at end of file diff --git a/app/Service/v3/Interfaces/SeparateAccountsServiceInterface.php b/app/Service/v3/Interfaces/SeparateAccountsServiceInterface.php index 0780d6b..c81cbdc 100644 --- a/app/Service/v3/Interfaces/SeparateAccountsServiceInterface.php +++ b/app/Service/v3/Interfaces/SeparateAccountsServiceInterface.php @@ -14,10 +14,11 @@ interface SeparateAccountsServiceInterface /** * (线上)订单确认完成分账 * 用户确认或服务商(服务站确认) - * @param $global_order_id + * @param $orderMainId + * @param $userId * @return mixed */ - public function orderOnlineCompleted($global_order_id); + public function orderOnlineCompleted($orderMainId, $userId); /** * (线下)订单支付完成分账 diff --git a/config/autoload/wechat.php b/config/autoload/wechat.php index 8739460..9802ac9 100644 --- a/config/autoload/wechat.php +++ b/config/autoload/wechat.php @@ -11,4 +11,8 @@ return [ 'app_id' => env('APP_ID',''), 'secret' => env('APP_SECRET',''), ], + 'notify_url' => [ + 'online' => env('SITE_HOST') . '/v3/wechat/notify/online', + 'offline' => env('SITE_HOST') . '/v3/wechat/notify/offline', + ] ]; \ No newline at end of file diff --git a/config/routes.php b/config/routes.php index 3de5cde..11a8405 100644 --- a/config/routes.php +++ b/config/routes.php @@ -120,7 +120,6 @@ Router::addGroup('/v3/', function () { Router::post('orderOnline/add', 'App\Controller\v3\OrderOnlineController@add'); Router::post('orderOffline/add', 'App\Controller\v3\OrderOfflineController@add'); Router::post('store/storeWithdrawalList', 'App\Controller\v3\BalanceStatementController@getWithdrawalListByStore'); - Router::post('payment/wechatpayOnline', 'App\Controller\v3\PaymentController@wechatpayOnline'); Router::post('store/getBusinessHours', 'App\Controller\v3\StoreController@getBusinessHours'); Router::post('store/updateBusinessHours', 'App\Controller\v3\StoreController@updateBusinessHours'); Router::post('userAddress/update', 'App\Controller\v3\UserAddressController@update'); @@ -130,6 +129,11 @@ Router::addGroup('/v3/', function () { Router::post('userAddress/delete', 'App\Controller\v3\UserAddressController@delete'); Router::post('coupon/getListByUser', 'App\Controller\v3\CouponController@getListByUser'); Router::post('shopCart/info', 'App\Controller\v3\ShopCartController@info'); + Router::post('orderOnline/pay', 'App\Controller\v3\OrderOnlineController@pay'); + Router::post('orderOnline/cancel', 'App\Controller\v3\OrderOnlineController@cancel'); + Router::post('orderOnline/del', 'App\Controller\v3\OrderOnlineController@del'); + Router::post('orderOnline/applyRefund', 'App\Controller\v3\OrderOnlineController@applyRefund'); + Router::post('orderOnline/complete', 'App\Controller\v3\OrderOnlineController@complete'); },['middleware' => [\App\Middleware\Auth\ApiMiddleware::class, \App\Middleware\Auth\UserMiddleware::class]]); // 微信支付回调