diff --git a/.gitignore b/.gitignore index 9454e2b..0e78326 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ vendor/ .phpunit* /watch .vscode/ +config/cert/apiclient_cert_2.pem +config/cert/apiclient_key_2.pem diff --git a/app/Amqp/Consumer/couponRebateConsumer.php b/app/Amqp/Consumer/couponRebateConsumer.php index a76f046..3417e2a 100644 --- a/app/Amqp/Consumer/couponRebateConsumer.php +++ b/app/Amqp/Consumer/couponRebateConsumer.php @@ -37,6 +37,9 @@ class couponRebateConsumer extends ConsumerMessage public function isEnable(): bool { + if(env('APP_ENV') == 'local') { + return false; + } return parent::isEnable(); } } diff --git a/app/Constants/ErrorCode.php b/app/Constants/ErrorCode.php index ca97510..fdb920a 100644 --- a/app/Constants/ErrorCode.php +++ b/app/Constants/ErrorCode.php @@ -54,4 +54,14 @@ class ErrorCode extends AbstractConstants */ const PAY_FAILURE = 400; + /** + * @Message("Separate Accounts Error!") + */ + const SEPARATE_ACCOUNTS_ERROR = 700; + +/** + * @Message("Goods failure!") + */ + const GOODS_FAILURE = 700; + } diff --git a/app/Constants/LogLabel.php b/app/Constants/LogLabel.php index edcb57c..2e92fd6 100644 --- a/app/Constants/LogLabel.php +++ b/app/Constants/LogLabel.php @@ -33,4 +33,37 @@ class LogLabel extends AbstractConstants * @Message("Order Log Label") */ const ORDER_LOG = 'order_log'; + + /** + * @Message("Separate Accounts Log Label") + */ + const SEPARATE_ACCOUNTS_LOG = 'separate_accounts_log'; + + /** + * @Message("Online Order Complete Log Label") + */ + const ONLINE_COMPLETE_LOG = 'online_complete_log'; + + /** + * @Message("Online Paid Complete Log Label") + */ + const ONLINE_PAID_LOG = 'online_paid_log'; + + /** + * @Message("Offline Paid Complete Log Label") + */ + const OFFLINE_PAID_LOG = 'offline_paid_log'; + + /** + * @Message("Pay refund Log Label") + */ + const WX_NOTIFY_REFUND = 'wx_notify_refund'; + + /** + * @Message("Pay refund Log Label") + */ + const WX_PAY_REFUND = 'wx_pay_refund'; + + const AUTO_CANCEL_USER_ORDER = 'auto_cancel_user_order_log'; + } diff --git a/app/Constants/SsdbKeysPrefix.php b/app/Constants/SsdbKeysPrefix.php index bf76f9d..0801b10 100644 --- a/app/Constants/SsdbKeysPrefix.php +++ b/app/Constants/SsdbKeysPrefix.php @@ -46,4 +46,10 @@ class SsdbKeysPrefix extends AbstractConstants * @Message("Coupon rebate List") */ const COUPON_REBATE_LIST = 'coupon_rebate_list_'; + + /** + * @Message("PURCHASE RECORD") + * + */ + const PURCHASE_RECORD = 'purchase_record_'; } diff --git a/app/Controller/CommunityController.php b/app/Controller/CommunityController.php new file mode 100644 index 0000000..5fa8ca4 --- /dev/null +++ b/app/Controller/CommunityController.php @@ -0,0 +1,29 @@ +validated(); + $jsonData = $data['json_data'] ?? json_encode([]); + $res = $this->userCommunityService->bindLimitByUser(UserRelationBind::BIND_TYPE_COMMUNITY, $data['source_id'], $data['user_id'], $jsonData); + return $this->success(['id' => $res->id]); + } + +} diff --git a/app/Controller/CouponController.php b/app/Controller/CouponController.php index dc8ae7c..5caf76c 100644 --- a/app/Controller/CouponController.php +++ b/app/Controller/CouponController.php @@ -199,65 +199,11 @@ class CouponController extends BaseController $type = $this->request->input('type', 1); # 店铺类型id $storetypeId = $this->request->input('storetype_id', 0); - $storetypeIds = explode(',', str_replace(',', ',', $storetypeId)); + # 购物车商品id + $carIds = $this->request->input('car_ids', 0); - $available = []; - $notAvailable = []; - - if ($this->empty($orderAmount) || $this->empty($userId)) { - return $this->success([ - 'available' => $available, - 'not_available' => array_values($notAvailable) - ]); - } - - // 获取用户优惠券 - $currentTime = time(); - - $data = Db::table('ims_system_coupon_user_receive as receive') - ->select([ - 'receive.id as receive_id', - 'receive.user_id', - 'receive.number_remain', - 'coupon.id', - 'coupon.title', - 'coupon.full_amount', - 'coupon.discounts', - 'coupon.usable_start_time', - 'coupon.usable_end_time', - 'coupon.discount_type' - ]) - ->join('ims_system_coupon_user as coupon', 'coupon.id', '=', 'receive.system_coupon_user_id') - ->where(['receive.user_id' => $userId]) - ->whereIn('receive.status', [0,1]) - ->where('receive.number_remain', '>', 0) - ->whereIn('coupon.type', [1,$type]) - ->where('coupon.full_amount', '<=', $orderAmount) - ->where('coupon.usable_start_time', '<=', $currentTime) - ->where('coupon.usable_end_time', '>=', $currentTime) - ->where('coupon.usable_number', '<=', Db::raw('receive.number_remain')) - ->where('coupon.market_id', 'in', [0, $marketId]) - ->whereIn('coupon.storetype_id', $storetypeIds) - ->orderByRaw('coupon.discounts DESC, coupon.full_amount DESC') - ->get(); - - // 分离用户今天用过的优惠券种类 - $container = ApplicationContext::getContainer(); - $redis = $container->get(Redis::class); - $couponIds = $redis->sMembers('coupon_'.date('Ymd').'_used_'.$userId); - - foreach ($data as $key => &$item) { - if (in_array($item->id, $couponIds)) { - $notAvailable[$item->id] = $item; - } else { - $available[] = $item; - } - } - - return $this->success([ - 'available' => $available, - 'not_available' => array_values($notAvailable) - ]); + $res = $this->couponService->getUserAvailableCoupons($orderAmount,$userId,$marketId,$type,$storetypeId,$carIds); + return $this->success($res); } diff --git a/app/Controller/NotifyController.php b/app/Controller/NotifyController.php index 955db3f..1073dc2 100644 --- a/app/Controller/NotifyController.php +++ b/app/Controller/NotifyController.php @@ -18,6 +18,8 @@ use App\Service\DeviceServiceInterface; use App\Service\FeiePrintServiceInterface; use App\Service\MiniprogramServiceInterface; use App\Service\MqttServiceInterface; +use App\Service\OrderServiceInterface; +use App\Service\SeparateAccountsServiceInterface; use App\Service\UserServiceInterface; use EasyWeChat\Factory; use Hyperf\DbConnection\Db; @@ -68,6 +70,18 @@ class NotifyController extends BaseController */ protected $couponRebateService; + /** + * @Inject + * @var OrderServiceInterface + */ + protected $orderService; + + /** + * @Inject + * @var SeparateAccountsServiceInterface + */ + protected $separateAccountsService; + public function wxminiOnline() { @@ -101,7 +115,7 @@ class NotifyController extends BaseController $message ); Db::rollBack(); - $fail('Unknown error but FAIL'); + return $fail('Unknown error but FAIL'); } // 查询订单 @@ -113,7 +127,7 @@ class NotifyController extends BaseController ->first(); // 订单不存在 - if (empty($orderMain)) { + if (empty($orderMain) || $orderMain->state == OrderMain::ORDER_STATE_DELIVERY) { $this->log->event( LogLabel::PAY_NOTIFY_WXMINI, ['global_order_id_fail' => $message['out_trade_no']] @@ -122,92 +136,82 @@ class NotifyController extends BaseController return true; } - // 修改订单、子订单状态 - $currentTime = time(); - $orderMain->state = OrderMain::ORDER_STATE_UNTAKE; - $orderMain->time_pay = $currentTime; - $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime); - $orderMain->save(); - - $upOrder = Order::query() - ->where(['order_main_id' => $orderMain->id]) - ->update(['state' => OrderMain::ORDER_STATE_UNTAKE, 'pay_time' => $orderMain->pay_time]); - - // 更新商户销量 - $upStoreScore = Store::query() - ->whereIn('id', explode(',', $orderMain->store_ids)) - ->update(['score' => Db::raw('score+1')]); - - // 更新商品库存和销量 - $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) - ->where(['order_main_id' => $orderMain->id]) - ->get() - ->toArray(); - $orderGoods = OrderGoods::query()->select(['good_id AS id', 'number', 'combination_id']) - ->whereIn('order_id', array_values(array_column($orders, 'id'))) - ->get() - ->toArray(); - foreach ($orderGoods as $key => &$goodsItem) { - - $goods = Goods::find($goodsItem['id']); - - // 库存处理,有规格 - if ($goodsItem['combination_id']) { - $combination = SpecCombination::find($goodsItem['combination_id']); - $combination->number = $combination->number - $goodsItem['number']; - $combination->save(); - } else { - $goods->inventory = $goods->inventory - $goodsItem['number']; - } - - $goods->sales = $goods->sales - $goodsItem['number']; - $goods->save(); - - } - - // 月销流水 - $statistics = []; - foreach ($orders as $key => &$order) { - $statistics[] = [ - 'money' => $order['money'], - 'user_id' => $order['user_id'], - 'store_id' => $order['store_id'], - 'market_id' => $orderMain->market_id, - 'order_id' => $order['id'], - 'createtime' => strtotime($order['pay_time']), - ]; - } - - if (is_array($statistics) && !empty($statistics)) { - $inSalesStatistics = OrderSalesStatistic::query()->insert($statistics); - } + $this->orderService->onlinePaid($message['out_trade_no']); + $this->separateAccountsService->orderOnlinePaid($message['out_trade_no']); + + // // 修改订单、子订单状态 + // $currentTime = time(); + // $orderMain->state = OrderMain::ORDER_STATE_UNTAKE; + // $orderMain->time_pay = $currentTime; + // $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime); + // $orderMain->save(); + // + // $upOrder = Order::query() + // ->where(['order_main_id' => $orderMain->id]) + // ->update(['state' => OrderMain::ORDER_STATE_UNTAKE, 'pay_time' => $orderMain->pay_time]); + // + // // 更新商户销量 + // $upStoreScore = Store::query() + // ->whereIn('id', explode(',', $orderMain->store_ids)) + // ->update(['score' => Db::raw('score+1')]); + // + // // 更新商品库存和销量 + // $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) + // ->where(['order_main_id' => $orderMain->id]) + // ->get() + // ->toArray(); + // $orderGoods = OrderGoods::query()->select(['good_id AS id', 'number', 'combination_id']) + // ->whereIn('order_id', array_values(array_column($orders, 'id'))) + // ->get() + // ->toArray(); + // foreach ($orderGoods as $key => &$goodsItem) { + // + // $goods = Goods::find($goodsItem['id']); + // + // // 库存处理,有规格 + // if ($goodsItem['combination_id']) { + // $combination = SpecCombination::find($goodsItem['combination_id']); + // $combination->number = $combination->number - $goodsItem['number']; + // $combination->save(); + // } else { + // $goods->inventory = $goods->inventory - $goodsItem['number']; + // } + // + // $goods->sales = $goods->sales - $goodsItem['number']; + // $goods->save(); + // + // } + // + // // 月销流水 + // $statistics = []; + // foreach ($orders as $key => &$order) { + // $statistics[] = [ + // 'money' => $order['money'], + // 'user_id' => $order['user_id'], + // 'store_id' => $order['store_id'], + // 'market_id' => $orderMain->market_id, + // 'order_id' => $order['id'], + // 'createtime' => strtotime($order['pay_time']), + // ]; + // } + // + // if (is_array($statistics) && !empty($statistics)) { + // $inSalesStatistics = OrderSalesStatistic::query()->insert($statistics); + // } // 优惠券返券 $this->couponRebateService->couponRebateInTask($orderMain->id); // 喇叭通知,兼容旧音响,MQTT+IOT $res = $this->mqttSpeakerService->speakToStore($orderMain->id); - $this->log->event( - LogLabel::PAY_NOTIFY_WXMINI, - ['fail_mqtt' => json_encode($res)] - ); $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id); - $this->log->event( - LogLabel::PAY_NOTIFY_WXMINI, - ['fail_device' => json_encode($res)] - ); + // 公众号模板消息 $res = $this->miniprogramService->sendTemMsgForOnlineOrder($orderMain->id); - $this->log->event( - LogLabel::PAY_NOTIFY_WXMINI, - ['fail_mini' => json_encode($res)] - ); - // 打印订单,自动打印 TODO 后续优化调用逻辑 + + // 打印订单,自动打印 $res = $this->feiePrintService->feiePrint($orderMain->global_order_id); - $this->log->event( - LogLabel::PAY_NOTIFY_WXMINI, - ['fail_feie' => json_encode($res)] - ); + Db::commit(); return true; @@ -218,7 +222,7 @@ class NotifyController extends BaseController ['exception_fail' => $e->getMessage()] ); Db::rollBack(); - $fail('Exception'); + return $fail('Exception'); } }); @@ -263,7 +267,7 @@ class NotifyController extends BaseController $message ); Db::rollBack(); - $fail('Unknown error but FAIL'); + return $fail('Unknown error but FAIL'); } // 查询订单 @@ -284,112 +288,105 @@ class NotifyController extends BaseController return true; } - // 修改订单、子订单状态 - $currentTime = time(); - $orderMain->state = OrderMain::ORDER_STATE_UNTAKE; - $orderMain->dm_state = OrderMain::ORDER_STATE_UNTAKE; - $orderMain->time_pay = $currentTime; - $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime); - $orderMain->save(); - - $upOrder = Order::query() - ->where(['order_main_id' => $orderMain->id]) - ->update([ - 'state' => OrderMain::ORDER_STATE_UNTAKE, - 'dm_state' => OrderMain::ORDER_STATE_UNTAKE, - 'pay_time' => date('Y-m-d H:i:s', $currentTime) - ]); - - // 查询子订单,当面付目前实际上只有一个子订单 - $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) - ->where(['order_main_id' => $orderMain->id]) - ->get() - ->toArray(); - - // 商户钱包、流水资金、奖励、发布模板消息处理 - foreach ($orders as $key => $orderItem) { - - $recordBase = [ - 'user_id' => $orderItem['user_id'], - 'order_id' => $orderItem['id'], - 'store_id' => $orderItem['store_id'], - 'type' => 1, - 'time' => date('Y-m-d H:i:s', $currentTime), - 'add_time' => $currentTime, - ]; - - // 钱包 - $store = Store::find($orderItem['store_id']); - $store->store_wallet = bcadd($store->store_wallet, $orderItem['money'], 2); - $store->save(); - - // 流水 - $record = [ - 'money' => $orderItem['money'], - 'note' => '当面付订单收入', - 'category' => 2, - ]; - StoreAccount::query()->insert(array_merge($recordBase, $record)); - - // 平台新用户奖励给商户 - $isStageNewUser = $this->userService->isStageNewUser($orderItem['user_id'], $orderMain->id); - $needAward = false; - $awardAmount = 0; - if ($isStageNewUser) { - $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_new_user'])->value('value'); - // 流水 - $record = [ - 'money' => $awardAmount, - 'note' => '新用户下单成功,平台奖励', - 'category' => 3, - ]; - $needAward = true; - } else { - $isStoreFirstOrderToday = $this->userService->isStoreFirstOrderToday($orderItem['user_id'],$orderItem['store_id'],$orderItem['id'], self::AWARD_LIMIT_AMOUNT); - if ($isStoreFirstOrderToday && $orderItem['money'] >= self::AWARD_LIMIT_AMOUNT) { - $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_each_order'])->value('value'); - // 流水 - $record = [ - 'money' => $awardAmount, - 'note' => '用户下单成功,平台奖励', - 'category' => 4, - ]; - $needAward = true; - } - } - - if ($needAward && $awardAmount) { - // 奖励钱包 - $store->refresh(); - $store->award_money = bcadd($store->award_money, $awardAmount, 2); - $store->save(); - - // 流水 - StoreAccount::query()->insert(array_merge($recordBase, $record)); - - // 发布公众号消息 - $openid = Users::query()->where(['id' => $store['user_id']])->value('openid'); - $res = $this->miniprogramService->sendTemMsgForAward($record['money'], $record['note'], $openid, $recordBase['time']); - } - } + $orderPaid = $this->orderService->offlinePaid($message['out_trade_no']); + $separate = $this->separateAccountsService->orderOfflinePaid($message['out_trade_no']); + + // // 修改订单、子订单状态 + // $currentTime = time(); + // $orderMain->state = OrderMain::ORDER_STATE_UNTAKE; + // $orderMain->dm_state = OrderMain::ORDER_STATE_UNTAKE; + // $orderMain->time_pay = $currentTime; + // $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime); + // $orderMain->save(); + // + // $upOrder = Order::query() + // ->where(['order_main_id' => $orderMain->id]) + // ->update([ + // 'state' => OrderMain::ORDER_STATE_UNTAKE, + // 'dm_state' => OrderMain::ORDER_STATE_UNTAKE, + // 'pay_time' => date('Y-m-d H:i:s', $currentTime) + // ]); + + // // 查询子订单,当面付目前实际上只有一个子订单 + // $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) + // ->where(['order_main_id' => $orderMain->id]) + // ->get() + // ->toArray(); + // + // // 商户钱包、流水资金、奖励、发布模板消息处理 + // foreach ($orders as $key => $orderItem) { + // + // $recordBase = [ + // 'user_id' => $orderItem['user_id'], + // 'order_id' => $orderItem['id'], + // 'store_id' => $orderItem['store_id'], + // 'type' => 1, + // 'time' => date('Y-m-d H:i:s', $currentTime), + // 'add_time' => $currentTime, + // ]; + // + // // 钱包 + // $store = Store::find($orderItem['store_id']); + // $store->store_wallet = bcadd($store->store_wallet, $orderItem['money'], 2); + // $store->save(); + // + // // 流水 + // $record = [ + // 'money' => $orderItem['money'], + // 'note' => '当面付订单收入', + // 'category' => 2, + // ]; + // StoreAccount::query()->insert(array_merge($recordBase, $record)); + // + // // 平台新用户奖励给商户 + // $isStageNewUser = $this->userService->isPlatformNewUser($orderItem['user_id'], $orderMain->id); + // $needAward = false; + // $awardAmount = 0; + // if ($isStageNewUser) { + // $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_new_user'])->value('value'); + // // 流水 + // $record = [ + // 'money' => $awardAmount, + // 'note' => '新用户下单成功,平台奖励', + // 'category' => 3, + // ]; + // $needAward = true; + // } else { + // $isStoreFirstOrderToday = $this->userService->isStoreFirstOrderToday($orderItem['user_id'],$orderItem['store_id'],$orderItem['id'], self::AWARD_LIMIT_AMOUNT); + // if ($isStoreFirstOrderToday && $orderItem['money'] >= self::AWARD_LIMIT_AMOUNT) { + // $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_each_order'])->value('value'); + // // 流水 + // $record = [ + // 'money' => $awardAmount, + // 'note' => '用户下单成功,平台奖励', + // 'category' => 4, + // ]; + // $needAward = true; + // } + // } + // + // if ($needAward && $awardAmount) { + // // 奖励钱包 + // $store->refresh(); + // $store->award_money = bcadd($store->award_money, $awardAmount, 2); + // $store->save(); + // + // // 流水 + // StoreAccount::query()->insert(array_merge($recordBase, $record)); + // + // // 发布公众号消息 + // $openid = Users::query()->where(['id' => $store['user_id']])->value('openid'); + // $res = $this->miniprogramService->sendTemMsgForAward($record['money'], $record['note'], $openid, $recordBase['time']); + // } + // } // 喇叭通知,兼容旧音响,MQTT+IOT $res = $this->mqttSpeakerService->speakToStore($orderMain->id); - $this->log->event( - LogLabel::PAY_NOTIFY_WXMINI, - ['fail_mqtt' => json_encode($res)] - ); $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id); - $this->log->event( - LogLabel::PAY_NOTIFY_WXMINI, - ['fail_device' => json_encode($res)] - ); + // 公众号模板消息 $res = $this->miniprogramService->sendTemMsgForOfflineOrder($orderMain->id); - $this->log->event( - LogLabel::PAY_NOTIFY_WXMINI, - ['fail_mini' => json_encode($res)] - ); + Db::commit(); return true; @@ -400,7 +397,7 @@ class NotifyController extends BaseController ['exception_fail' => $e->getMessage()] ); Db::rollBack(); - $fail('Exception'); + return $fail('Exception'); } }); diff --git a/app/Controller/NotifyPayRefundController.php b/app/Controller/NotifyPayRefundController.php new file mode 100644 index 0000000..dbeb6fa --- /dev/null +++ b/app/Controller/NotifyPayRefundController.php @@ -0,0 +1,122 @@ +log->event( + LogLabel::WX_NOTIFY_REFUND, + '进入回调' + ); + $config = config('wxpay'); + $app = Factory::payment($config); + $app['guzzle_handler'] = CoroutineHandler::class; + + $get = $this->request->getQueryParams(); + $post = $this->request->getParsedBody(); + $cookie = $this->request->getCookieParams(); + $files = $this->request->getUploadedFiles(); + $server = $this->request->getServerParams(); + $xml = $this->request->getBody()->getContents(); + + $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml); + + /* 通知回调,进行业务处理 */ + $response = $app->handleRefundedNotify(function ($message, $fail) use ($app) { + $this->log->event( + LogLabel::WX_NOTIFY_REFUND, + $message + ); + try { + /* --- 退款失败 --- */ + if ( + empty($message) + || !isset($message['result_code']) + || $message['result_code'] != 'SUCCESS' + ) { + // 错误日志 + $this->log->event( + LogLabel::WX_NOTIFY_REFUND, + $message + ); + $fail('Unknown error but FAIL'); + return false; + } + + /* --- 退款成功 --- */ + $orderMain = OrderMain::select('id','global_order_id','money','user_id') + ->where('global_order_id',$message['out_trade_no']) + ->where('state',OrderMain::ORDER_STATE_REFUNDED) + ->where(Db::raw('refund_time is null')) + ->first(); + + if(!empty($orderMain)){ + // 添加退款时间 + $orderMain->refund_time = time(); + $orderMain->save(); + + // 退款返还优惠券 + $this->couponService->orderRefundCoupons($orderMain->global_order_id); + + // 删除特价商品缓存 + $this->purchaseLimitService->delSsdbPurchaseRecord($orderMain->id); + + // 添加用户的流水 + $this->financialService->userByOLOrderRefund($orderMain->user_id, $orderMain->global_order_id, $orderMain->money); + } + } catch (\Exception $e) { + + $this->log->event( + LogLabel::WX_NOTIFY_REFUND, + ['exception_fail' => $e->getMessage()] + ); + $fail('Exception'); + } + }); + + return $this->response + ->withHeader('Content-Type', 'text/xml') + ->withStatus(200) + ->withBody(new SwooleStream($response->getContent())); + } +} \ No newline at end of file diff --git a/app/Controller/OrderController.php b/app/Controller/OrderController.php index f26045d..5aa7160 100644 --- a/app/Controller/OrderController.php +++ b/app/Controller/OrderController.php @@ -3,11 +3,18 @@ namespace App\Controller; use App\Constants\ErrorCode; +use App\Constants\LogLabel; +use App\Model\OrderMain; use App\Request\OrderOfflineRequest; use App\Request\OrderOnlineRequest; +use App\Request\OnlineCancelRequest; +use App\Request\UserOrdersRequest; +use App\Service\SeparateAccountsServiceInterface; +use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; use App\Service\OrderServiceInterface; use Hyperf\HttpMessage\Stream\SwooleStream; +use Hyperf\Validation\ValidationException; class OrderController extends BaseController { @@ -18,6 +25,12 @@ class OrderController extends BaseController */ protected $orderService; + /** + * @Inject + * @var SeparateAccountsServiceInterface + */ + protected $separateAccountsService; + public function addOnlineOrder(OrderOnlineRequest $request) { $orderMainId = $this->orderService->addOnlineOrder($request->validated()); @@ -35,4 +48,87 @@ class OrderController extends BaseController } return $this->success(['order_id' => $orderMainId]); } + + /** + * 用户完成订单-确认收货 + */ + public function userComp() + { + + $validator = $this->validationFactory->make( + $this->request->all(), + [ + 'user_id' => 'required|nonempty|integer', + 'order_id' => 'required|nonempty|numeric', + ], + [ + '*.*' => ':attribute 参数不正确', + ] + ); + + if ($validator->fails()) { + // Handle exception + throw new ValidationException($validator); + return; + } + + $userId = $this->request->input('user_id'); + $orderId = $this->request->input('order_id'); // TODO 等新订单列表接口处理完毕后全面转换成global_order_id + $orderMain = OrderMain::query() + ->where(['id' => $orderId, 'state' => OrderMain::ORDER_STATE_DELIVERY, 'user_id' => $userId]) + ->first(); + + if (empty($orderMain)) { + $this->log->event(LogLabel::ONLINE_COMPLETE_LOG, ['order_not_found' => 'order_not_found']); + return $this->result(ErrorCode::SEPARATE_ACCOUNTS_ERROR, '', '操作失败,订单异常或不存在'); + } + + Db::beginTransaction(); + try { + + $this->orderService->onlineCompleted($orderMain->global_order_id); + $this->separateAccountsService->orderOnlineCompleted($orderMain->global_order_id); + + Db::commit(); + return $this->success(''); + } catch (\Exception $e) { + + Db::rollBack(); + $this->log->event(LogLabel::ONLINE_COMPLETE_LOG, ['exception' => $e->getMessage()]); + return $this->result(ErrorCode::SEPARATE_ACCOUNTS_ERROR, '', '操作失败,请稍后重试'); + } + + } + + /** + * 用户取消订单 + * @param OnlineCancelRequest $request + */ + public function onlineCancel(OnlineCancelRequest $request){ + $orderId = $request->input('order_id'); + $orderMain = OrderMain::where('id',$orderId) + ->select('global_order_id') + ->first(); + $res = $this->orderService->onlineCancel($orderMain->global_order_id); + if($res){ + return $this->success($res); + }else{ + return $this->result(ErrorCode::ORDER_FAILURE, '', '取消订单失败'); + } + } + + /** + * 用户订单 + * @param UserOrdersRequest $request + * @return \Psr\Http\Message\ResponseInterface + */ + public function userOnlineOrders(UserOrdersRequest $request) + { + $params = $request->validated(); + $this->orderService->onlineAutoCancelByUserId($params['user_id']); + $result = $this->orderService->userOnlineOrders($params['user_id'], $params['state'], $params['page'], $params['pagesize']); + + return $this->success($result); + } + } \ No newline at end of file diff --git a/app/Controller/PaymentController.php b/app/Controller/PaymentController.php index b2c6fba..c6c9788 100644 --- a/app/Controller/PaymentController.php +++ b/app/Controller/PaymentController.php @@ -3,14 +3,24 @@ namespace App\Controller; use App\Constants\ErrorCode; +use App\Model\Order; +use App\Model\OrderGoods; use App\Model\OrderMain; use App\Request\WxminiPayRequest; - +use Hyperf\Di\Annotation\Inject; +use App\Service\PurchaseLimitServiceInterface; use EasyWeChat\Factory; +use Hyperf\DbConnection\Db; use Hyperf\Guzzle\CoroutineHandler; - +use App\Constants\LogLabel; +use App\Commons\Log; class PaymentController extends BaseController { + /** + * @Inject + * @var PurchaseLimitServiceInterface + */ + protected $purchaseLimitService; public function wxminiPayOnline(WxminiPayRequest $request){ @@ -30,10 +40,28 @@ class PaymentController extends BaseController return $this->result(ErrorCode::PAY_FAILURE, $data,'订单不存在或已失效'); } + //查询订单商品信息 + $order = Order::query() + ->where('order_main_id',$data['order_id']) + ->select('id') + ->get() + ->toArray(); + $orderGoods = OrderGoods::query() + ->whereIn('order_id',$order) + ->get(); + //判断是否有购买多个特价商品 + $result = $this->purchaseLimitService->PurchaseLimit($orderGoods); + if(!$result){ + Db::rollBack(); + $this->log->event(LogLabel::ORDER_LOG, ['msg'=> '支付失败,同一订单不能存在多个特价商品','global_order_id' => $orderMain->global_order_id]); + return $this->result(ErrorCode::PAY_FAILURE, $data,'同一订单不能存在多个特价商品'); + } + $result = $app->order->unify([ 'body' => '懒族生活 - 外卖下单', 'out_trade_no' => $orderMain->global_order_id, - 'total_fee' => bcmul(floatval($orderMain->money), 100, 0), + // 'total_fee' => bcmul(floatval($orderMain->money), 100, 0), + 'total_fee' => 1, 'notify_url' => config('site_host') . '/wechat/notify/wxminionline', 'trade_type' => 'JSAPI', 'openid' => $data['openid'], diff --git a/app/Controller/PurchaseLimitController.php b/app/Controller/PurchaseLimitController.php new file mode 100644 index 0000000..7bb2d22 --- /dev/null +++ b/app/Controller/PurchaseLimitController.php @@ -0,0 +1,37 @@ +purchaseLimitService->getStoreIdByMarketId($this->request->all()); + return $this->success($res); + } + + public function ssdbPurchaseRecord() + { + $res = $this->purchaseLimitService->ssdbPurchaseRecord($this->request->all(),214,156813021196050432); + return $this->success($res); + } + + public function delSsdbPurchaseRecord() + { + $res = $this->purchaseLimitService->delSsdbPurchaseRecord($this->request->input('order_id')); + return $this->success($res); + } + +} diff --git a/app/Controller/ShopCarController.php b/app/Controller/ShopCarController.php new file mode 100644 index 0000000..8c6cb35 --- /dev/null +++ b/app/Controller/ShopCarController.php @@ -0,0 +1,39 @@ +shopCarService->addShopCar($this->request->all()); + if (isset($res['error'])) { + return $this->result(ErrorCode::GOODS_FAILURE, '', $res['error']); + } + return $this->success($res); + } + + public function updateShopCar() + { + $res = $this->shopCarService->updateShopCar($this->request->all()); + if (isset($res['error'])) { + return $this->result(ErrorCode::GOODS_FAILURE, '', $res['error']); + } + return $this->success($res); + } + +} diff --git a/app/JsonRpc/OrderService.php b/app/JsonRpc/OrderService.php new file mode 100644 index 0000000..aa631e4 --- /dev/null +++ b/app/JsonRpc/OrderService.php @@ -0,0 +1,91 @@ +orderService->onlineCompleted($global_order_id); + $this->separateAccountsService->orderOnlineCompleted($global_order_id); + + Db::commit(); + return [ + "status" => 200, + "code" => 0, + "result" => [], + "message" => '调用成功' + ]; + } catch (\Exception $e) { + + Db::rollBack(); + $this->log->event(LogLabel::ONLINE_COMPLETE_LOG, ['exception' => $e->getMessage()]); + return [ + "status" => 200, + "code" =>ErrorCode::SEPARATE_ACCOUNTS_ERROR, + "result" => [], + "message" => ErrorCode::getMessage(ErrorCode::SEPARATE_ACCOUNTS_ERROR) + ]; + } + + } + + /** + * 线上订单退款 + * 申请退款 state = 8 + * 退款成功 state = 9 + */ + public function onlineRefund($global_order_id){ + $result = [ + "status" => 200, + "code" => ErrorCode::ORDER_FAILURE, + "result" => [], + "message" => '' + ]; + + $res = $this->orderService->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/OrderServiceInterface.php b/app/JsonRpc/OrderServiceInterface.php new file mode 100644 index 0000000..6292ffe --- /dev/null +++ b/app/JsonRpc/OrderServiceInterface.php @@ -0,0 +1,8 @@ +extend('exists_enable', function ($attribute, $value, $parameters, $validator) { + + // 查询 + $builder = Db::table($parameters[0])->where($parameters[1], '=', $value); + + $whereArr = array_slice($parameters,2); + if (!empty($whereArr)) { + foreach ($whereArr as $key => $where) { + $builder->whereRaw($where); + } + } + + return $builder->exists(); + }); + + // 注册了 not_equal 验证器规则,参数是anotherfield,table,primary_field,foreign_field + // 要排除对比的字段请求参数名、表名、本参数对应表id、比较字段 + $validatorFactory->extend('not_equal', function ($attribute, $value, $parameters, $validator) { + + // 获取比较字段参数值 + $foreignValue = $validator->getData()[$parameters[0]]; + + // 查询 + $builder = Db::table($parameters[1]) + ->where($parameters[2], '=', $value) + ->where($parameters[3], '!=', $foreignValue) + ; + + return $builder->exists(); + }); + // 注册了 base64 验证器规则 $validatorFactory->extend('base64', function ($attribute, $value, $parameters, $validator) { @@ -78,36 +111,40 @@ class ValidatorFactoryResolvedListener implements ListenerInterface }); - // 注册了 exists_enable 验证器规则,参数是table,field,where1,where2... - $validatorFactory->extend('exists_enable', function ($attribute, $value, $parameters, $validator) { - - // 查询 - $builder = Db::table($parameters[0])->where($parameters[1], '=', $value); + // 注册了 file_different_if_file 验证器规则 + // file_different_if_file:field 两文件字段不能是同一个文件 + $validatorFactory->extend('file_different_if_file', function ($attribute, $value, $parameters, $validator) { - $whereArr = array_slice($parameters,2); - if (!empty($whereArr)) { - foreach ($whereArr as $key => $where) { - $builder->whereRaw($where); - } + // 获取比较字段参数值 + $anotherFile = $validator->getData()[$parameters[0]]; + if (!($value instanceof UploadedFile && $anotherFile instanceof UploadedFile)) { + return true; } + return md5_file($value->getRealPath()) !== md5_file($anotherFile->getRealPath()); - return $builder->exists(); }); - // 注册了 not_equal 验证器规则,参数是anotherfield,table,primary_field,foreign_field - // 要排除对比的字段请求参数名、表名、本参数对应表id、比较字段 - $validatorFactory->extend('not_equal', function ($attribute, $value, $parameters, $validator) { + // 注册了 tel 验证器规则 + // 手机号码验证器 + $validatorFactory->extend('tel', function ($attribute, $value, $parameters, $validator) { + return boolval(preg_match('/^1[3-9]\d{9}$/', $value)); + }); - // 获取比较字段参数值 - $foreignValue = $validator->getData()[$parameters[0]]; + // 注册了 image_if_file 验证器规则 + // 如果是文件就必须是图片类型的 + $validatorFactory->extend('image_if_file', function ($attribute, $value, $parameters, $validator) { - // 查询 - $builder = Db::table($parameters[1]) - ->where($parameters[2], '=', $value) - ->where($parameters[3], '!=', $foreignValue) - ; + if (!($value instanceof UploadedFile)) { + return true; + } + + $rules = $validator->getRules(); + $rules[$attribute] = ['image']; + $validator->setRules($rules); + + return $validator->passes(); - return $builder->exists(); }); + } } \ No newline at end of file diff --git a/app/Model/AdminUser.php b/app/Model/AdminUser.php new file mode 100644 index 0000000..d2ed2b6 --- /dev/null +++ b/app/Model/AdminUser.php @@ -0,0 +1,29 @@ +=100是提现消费等支出项 + */ + const MONEY_TYPE_CS_PLAT_NEW_USER = 1; // 社区服务点新用户奖励(线上订单完成) + const MONEY_TYPE_CS_FIRST_ORDER = 2; // 社区服务点新用户线上首单奖励(线上订单完成) + const MONEY_TYPE_CS_OL_ORDER = 3; // 社区服务点用户线上订单分账(线上订单完成) + const MONEY_TYPE_STORE_PLAT_NEW_USER = 4; // 商户平台新用户奖励 + const MONEY_TYPE_STORE_FIRST_ORDER = 5; // 商户当日首单奖励 + const MONEY_TYPE_STORE_OL_ORDER_COMP = 6; // 商户线上订单完成收入 + const MONEY_TYPE_STORE_OFL_ORDER_COMP = 7; // 商户线下订单完成收入 + const MONEY_TYPE_USER_OL_ORDER_REFUND = 8; // 用户线上订单退款 + + const MONEY_TYPE_USER_OFL_ORDER = 100; // 用户线下支付订单 + const MONEY_TYPE_USER_OL_ORDER = 101; // 用户线上支付订单 + + /** + * 状态 + */ + const STATUS_NORMAL = 1; + const STATUS_ABNORMAL = 2; + + /** + * The table associated with the model. + * + * @var string + */ + protected $table = 'lanzu_financial_record'; + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'user_id', + 'user_type', + 'money', + 'money_type', + 'source_id', + 'source_type', + 'desc', + 'comment', + 'status', + ]; + /** + * The attributes that should be cast to native types. + * + * @var array + */ + protected $casts = []; +} \ No newline at end of file diff --git a/app/Model/Market.php b/app/Model/Market.php new file mode 100644 index 0000000..4d1a2d0 --- /dev/null +++ b/app/Model/Market.php @@ -0,0 +1,30 @@ +getTable(); + $this->setTable($tableName.'_'.$suffix); + return $this; + } } diff --git a/app/Model/OrderMain.php b/app/Model/OrderMain.php index 92213ad..3aa12e0 100644 --- a/app/Model/OrderMain.php +++ b/app/Model/OrderMain.php @@ -11,6 +11,9 @@ class OrderMain extends Model // 线下订单,当面付 const ORDER_TYPE_OFFLINE = 4; + const ORDER_DEL_YES = 1; + const ORDER_DEL_NO = 2; + // 订单状态 // 待付款 const ORDER_STATE_UNPAY = 1; @@ -32,6 +35,8 @@ class OrderMain extends Model const ORDER_STATE_REFUNDED = 9; // 拒绝退款 const ORDER_STATE_UNREFUND = 10; + // 完成状态组合 + const ORDER_STATE_FINISH = [self::ORDER_STATE_COMPLETE, self::ORDER_STATE_EVALUATED, self::ORDER_STATE_UNREFUND]; // 订单支付方式 // 微信支付 diff --git a/app/Model/ServiceReward.php b/app/Model/ServiceReward.php new file mode 100644 index 0000000..583ad0a --- /dev/null +++ b/app/Model/ServiceReward.php @@ -0,0 +1,33 @@ + 'array' + ]; +} \ No newline at end of file diff --git a/app/Model/ShopCar.php b/app/Model/ShopCar.php new file mode 100644 index 0000000..dfabd17 --- /dev/null +++ b/app/Model/ShopCar.php @@ -0,0 +1,14 @@ +attributes['json_data'] = $value ? json_encode(json_decode($value, true)) : ''; + } + +} \ No newline at end of file diff --git a/app/Model/Users.php b/app/Model/Users.php index 32cff4d..9ae2733 100644 --- a/app/Model/Users.php +++ b/app/Model/Users.php @@ -4,6 +4,12 @@ namespace App\Model; class Users extends Model { + // 用户账户(钱包)操作 增 + const WALLET_TYPE_INC = 1; + // 用户账户(钱包)操作 减 + const WALLET_TYPE_DEC = 2; + protected $table = 'ims_cjdc_user'; + public $timestamps = false; } \ No newline at end of file diff --git a/app/Request/CommunityBindRequest.php b/app/Request/CommunityBindRequest.php new file mode 100644 index 0000000..6fe4841 --- /dev/null +++ b/app/Request/CommunityBindRequest.php @@ -0,0 +1,45 @@ + 'required|nonempty', + 'user_id' => 'required|nonempty|exists_enable:ims_cjdc_user,id', + 'json_data' => 'json', + ]; + } + + public function messages(): array + { + return [ + '*.nonempty' => ':attribute参数异常', + 'user_id.exists_enable' => '用户不存在', + ]; + } + + public function attributes(): array + { + return [ + + ]; + } +} diff --git a/app/Request/OnlineCancelRequest.php b/app/Request/OnlineCancelRequest.php new file mode 100644 index 0000000..5cea6d8 --- /dev/null +++ b/app/Request/OnlineCancelRequest.php @@ -0,0 +1,40 @@ + 'required|nonempty|integer|exists:ims_cjdc_order_main,id', + ]; + } + + public function messages(): array + { + return [ + 'order_id.*' => ':attribute信息不正确', + ]; + } + + public function attributes(): array + { + return [ + 'order_id' => '订单号', + ]; + } +} diff --git a/app/Request/OrderOnlineRequest.php b/app/Request/OrderOnlineRequest.php index 019cc99..b02144f 100644 --- a/app/Request/OrderOnlineRequest.php +++ b/app/Request/OrderOnlineRequest.php @@ -20,7 +20,6 @@ class OrderOnlineRequest extends BaseFormRequest public function rules(): array { return [ - 'order_num' => 'nonempty', 'delivery_no' => '', 'dada_fee' => 'nonempty', 'market_id' => 'required|nonempty|integer', diff --git a/app/Request/UpdateShopCarRequest.php b/app/Request/UpdateShopCarRequest.php new file mode 100644 index 0000000..64a7748 --- /dev/null +++ b/app/Request/UpdateShopCarRequest.php @@ -0,0 +1,43 @@ + 'required|nonempty|integer|exists_enable:ims_cjdc_shopcar,id', + ]; + } + + public function messages(): array + { + return [ + 'id.exists_enable' => ':attribute不存在或被禁用', + 'service_personnel_id.*' => ':attribute信息不正确' + ]; + } + + public function attributes(): array + { + return [ + 'id' => '购物车记录', + ]; + } +} diff --git a/app/Request/UserOrdersRequest.php b/app/Request/UserOrdersRequest.php new file mode 100644 index 0000000..092f96e --- /dev/null +++ b/app/Request/UserOrdersRequest.php @@ -0,0 +1,39 @@ + 'required|nonempty|integer', + 'market_id' => 'required|nonempty|integer', + 'state' => 'required', + 'page' => 'required|nonempty|integer', + 'pagesize' => 'required|nonempty|integer', + ]; + } + + public function messages(): array + { + return [ + '*.*' => ':attribute 参数不正确', + ]; + } +} diff --git a/app/Service/CouponService.php b/app/Service/CouponService.php index eb726f0..5aef5b2 100644 --- a/app/Service/CouponService.php +++ b/app/Service/CouponService.php @@ -2,11 +2,14 @@ namespace App\Service; +use App\Model\OrderMain; +use App\Model\ShopCar; use Hyperf\Di\Annotation\Inject; use Hyperf\DbConnection\Db; use App\Model\CouponUserRecType; use App\Model\Coupon; use App\Model\CouponRec; +use App\Model\CouponUserUse; use Hyperf\Utils\ApplicationContext; use App\TaskWorker\SSDBTask; use App\Constants\SsdbKeysPrefix; @@ -18,7 +21,7 @@ use Hyperf\Redis\Redis; class CouponService implements CouponServiceInterface { - /** + /** * @Inject * @var Log */ @@ -153,9 +156,80 @@ class CouponService implements CouponServiceInterface * 获取用户当前订单可用的优惠券列表 * 按分类(1订单 等优惠)分组返回 */ - public function getUserAvailableCoupons() + public function getUserAvailableCoupons($orderAmount,$userId,$marketId,$type,$storetypeId,$carIds) { + $available = []; + $notAvailable = []; + $storetypeIds = explode(',', str_replace(',', ',', $storetypeId)); + + if (empty($orderAmount) || empty($userId)) { + return [ + 'available' => $available, + 'not_available' => array_values($notAvailable) + ]; + } + + // 获取用户优惠券 + $currentTime = time(); + + $data = Db::table('ims_system_coupon_user_receive as receive') + ->select([ + 'receive.id as receive_id', + 'receive.user_id', + 'receive.number_remain', + 'coupon.id', + 'coupon.title', + 'coupon.full_amount', + 'coupon.discounts', + 'coupon.usable_start_time', + 'coupon.usable_end_time', + 'coupon.discount_type' + ]) + ->join('ims_system_coupon_user as coupon', 'coupon.id', '=', 'receive.system_coupon_user_id') + ->where(['receive.user_id' => $userId]) + ->whereIn('receive.status', [0,1]) + ->where('receive.number_remain', '>', 0) + ->whereIn('coupon.type', [1,$type]) + ->where('coupon.full_amount', '<=', $orderAmount) + ->where('coupon.usable_start_time', '<=', $currentTime) + ->where('coupon.usable_end_time', '>=', $currentTime) + ->where('coupon.usable_number', '<=', Db::raw('receive.number_remain')) + ->where('coupon.market_id', 'in', [0, $marketId]) + ->whereIn('coupon.storetype_id', $storetypeIds) + ->orderByRaw('coupon.discounts DESC, coupon.full_amount DESC') + ->get(); + + // 分离用户今天用过的优惠券种类 + $container = ApplicationContext::getContainer(); + $redis = $container->get(Redis::class); + $couponIds = $redis->sMembers('coupon_'.date('Ymd').'_used_'.$userId); + + foreach ($data as $key => &$item) { + if (in_array($item->id, $couponIds)) { + $item->msg = '今日已使用'; + $notAvailable[$item->id] = $item; + } else { + $available[] = $item; + } + } + + //如果存在特价商品 不给用券 + $carIdsArr = explode(',',$carIds); + $shopCarExists = ShopCar::whereIn('id',$carIdsArr) + ->where('money',0.01) + ->exists(); + if($shopCarExists){ + foreach ($available as $k => $v) { + $v->msg = '不可使用'; + $notAvailable[$v->id] = $v; + } + $available = []; + } + return [ + 'available' => $available, + 'not_available' => array_values($notAvailable) + ]; } /** @@ -220,4 +294,68 @@ class CouponService implements CouponServiceInterface return $setRes&&$expireRes; } + /* 删除-优惠券今日使用的缓存 + * @param $userId + * @param $couponId + * @return bool + */ + public function clearTodayCouponUsed($userId, $couponId) + { + + $redis = ApplicationContext::getContainer()->get(Redis::class); + + $res = $redis->sRem( + 'coupon_'.date('Ymd').'_used_'.$userId, + $couponId + ); + return $res; + } + + /** + * 退款返还优惠券 + * 先查询是否正常使用优惠券 + * 修改状态,退还领取记录库存,删除ssdb缓存 + */ + public function orderRefundCoupons($global_order_id) + { + $order_main = OrderMain::where('global_order_id',$global_order_id) + ->select('id','user_id') + ->first(); + $time = time(); + Db::beginTransaction(); + try { + $couponUses = CouponUserUse::query() + ->select('id','system_coupon_id','user_id','number','user_receive_id') + ->where('order_main_id',$order_main->id) + ->where('status',CouponUserUse::COUPON_USE_STATE_USED) + ->get(); + if(!empty($couponUses)){ + foreach($couponUses as $use){ + $use->status = CouponUserUse::COUPON_USE_STATE_CANCEL; + $use->return_time = $time; + $use->update_time = $time; + $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,' . CouponRec::STATE_UNUSED . ',' . CouponRec::STATE_SOME . ')'), + 'update_time' => $time + ]); + + $clearUseRedis = $this->clearTodayCouponUsed($use->user_id,$use->system_coupon_id); + } + } + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::ORDER_LOG, ['msg'=> '订单退款','exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + } } \ No newline at end of file diff --git a/app/Service/CouponServiceInterface.php b/app/Service/CouponServiceInterface.php index bdd60c5..33bf11b 100644 --- a/app/Service/CouponServiceInterface.php +++ b/app/Service/CouponServiceInterface.php @@ -13,7 +13,7 @@ interface CouponServiceInterface public function getUserReceiveCouponList(); - public function getUserAvailableCoupons(); + public function getUserAvailableCoupons($orderAmount,$userId,$marketId,$type,$storetypeId,$carIds); /** * 当前订单可用优惠券列表 @@ -26,5 +26,6 @@ interface CouponServiceInterface * @return mixed */ public function getOrderCanUseCoupons($orderAmount, $marketId, $userId, $fields=[], $type=1, $storeTypeIds=[0]); - + public function clearTodayCouponUsed($userId, $couponId); + public function orderRefundCoupons($global_order_id); } diff --git a/app/Service/FeiePrintService.php b/app/Service/FeiePrintService.php index 9f8f31d..114510b 100644 --- a/app/Service/FeiePrintService.php +++ b/app/Service/FeiePrintService.php @@ -37,6 +37,9 @@ class FeiePrintService implements FeiePrintServiceInterface ->orderBy('s.id') ->get() ->toArray(); + if (empty($data)) { + return ; + } foreach ($data as $key => &$item) { $item = (array)$item; } diff --git a/app/Service/FinancialRecordService.php b/app/Service/FinancialRecordService.php new file mode 100644 index 0000000..1da8f0d --- /dev/null +++ b/app/Service/FinancialRecordService.php @@ -0,0 +1,296 @@ +record( + FinancialRecord::ACCOUNT_LEDGER, + [ + 'user_id' => FinancialRecord::ACCOUNT_LEDGER, + 'user_type' => FinancialRecord::USER_TYPE_LEDGER, + 'money' => $money, + 'money_type' => $money_type, + 'source_id' => $source_id, + 'source_type' => $source_type, + 'desc' => $desc, + 'comment' => $comment, + 'status' => FinancialRecord::STATUS_NORMAL, + ], + true + ); + } + + public function record($user_id, $record, $isLedger=false) + { + $financialRecord = new FinancialRecord(); + + if (!$isLedger) { + $mod = bcmod((string)$user_id, '5', 0); + $financialRecord->suffix($mod); + } + + return $financialRecord->fill( + [ + 'user_id' => $user_id, + 'user_type' => $record['user_type'], + 'money' => $record['money'], + 'money_type' => $record['money_type'], + 'source_id' => $record['source_id'], + 'source_type' => $record['source_type'], + 'desc' => $record['desc'], + 'comment' => $record['comment'], + 'status' => $record['status'], + ] + )->save(); + + } + + /** + * @inheritDoc + */ + public function communityAwardByPlatNewUser( + $user_id, + $source_id, + $money, + $user_type=FinancialRecord::USER_TYPE_CS, + $source_type=FinancialRecord::SOURCE_TYPE_ORDER, + $money_type=FinancialRecord::MONEY_TYPE_CS_PLAT_NEW_USER, + $desc='新用户奖励', + $comment='社区服务点' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + // 维护社区服务点余额 + $balance = UserBalance::firstOrNew([ + 'user_type' => UserBalance::USER_TYPE_CS, + 'source_id' => $user_id + ]); + $balance->balance = bcadd($balance->balance, $money, 2); + $balance->save(); + + // 发送短信 + $this->smsAliService->sendForCommunityFinancial($user_id, $money); + + } + + /** + * @inheritDoc + */ + public function communityAwardByPlatNewUserFirstOLOrder( + $user_id, + $source_id, + $money, + $user_type=FinancialRecord::USER_TYPE_CS, + $source_type=FinancialRecord::SOURCE_TYPE_ORDER, + $money_type=FinancialRecord::MONEY_TYPE_CS_FIRST_ORDER, + $desc='新用户首单奖励', + $comment='社区服务点' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + // 维护社区服务点余额 + $balance = UserBalance::firstOrNew([ + 'user_type' => UserBalance::USER_TYPE_CS, + 'source_id' => $user_id + ]); + $balance->balance = bcadd($balance->balance, $money, 2); + $balance->save(); + + // 发送短信 + $this->smsAliService->sendForCommunityFinancial($user_id, $money); + } + + /** + * @inheritDoc + */ + public function communitySeparateAccountsByOrderComp( + $user_id, + $source_id, + $money, + $user_type=FinancialRecord::USER_TYPE_CS, + $source_type=FinancialRecord::SOURCE_TYPE_ORDER, + $money_type=FinancialRecord::MONEY_TYPE_CS_OL_ORDER, + $desc='用户订单分成', + $comment='社区服务点' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + // 维护社区服务点余额 + $balance = UserBalance::firstOrNew([ + 'user_type' => UserBalance::USER_TYPE_CS, + 'source_id' => $user_id + ]); + $balance->balance = bcadd($balance->balance, $money,2); + $balance->save(); + + // 发送短信 + $this->smsAliService->sendForCommunityFinancial($user_id, $money); + } + + + /** + * @inheritDoc + */ + public function storeAwardByPlatNewUserOFLOrder( + $user_id, + $source_id, + $money, + $user_type=FinancialRecord::USER_TYPE_STORE, + $source_type=FinancialRecord::SOURCE_TYPE_ORDER, + $money_type=FinancialRecord::MONEY_TYPE_STORE_PLAT_NEW_USER, + $desc='新用户下单奖励', + $comment='用户当面付商户奖励' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + // 同时维护钱包 + $store = Store::query()->where(['user_id' => $user_id])->first(); + $store->award_money = bcadd($store->award_money, $money, 2); + $store->save(); + } + + /** + * @inheritDoc + */ + public function storeAwardByTodayFirstOFLOrder( + $user_id, + $source_id, + $money, + $user_type=FinancialRecord::USER_TYPE_STORE, + $source_type=FinancialRecord::SOURCE_TYPE_ORDER, + $money_type=FinancialRecord::MONEY_TYPE_STORE_FIRST_ORDER, + $desc='用户店铺首单奖励', + $comment='用户当面付商户奖励' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + // 同时维护钱包 + $store = Store::query()->where(['user_id' => $user_id])->first(); + $store->award_money = bcadd($store->award_money, $money, 2); + $store->save(); + } + + public function recordAll($user_id, $source_id, $money, $user_type=1, $source_type=0, $money_type=0, $desc='', $comment='') { + $this->record( + $user_id, + [ + 'user_id' => $user_id, + 'user_type' => $user_type, + 'money' => $money, + 'money_type' => $money_type, + 'source_id' => $source_id, + 'source_type' => $source_type, + 'desc' => $desc, + 'comment' => $comment, + 'status' => FinancialRecord::STATUS_NORMAL, + ] + ); + + $this->ledgerAccounts($source_id, $money, $source_type, $money_type, $desc, $comment); + } + + /** + * @inheritDoc + */ + public function userByOFLOrderPaid( + $user_id, + $source_id, + $money, + $user_type=FinancialRecord::USER_TYPE_USER, + $source_type=FinancialRecord::SOURCE_TYPE_ORDER, + $money_type=FinancialRecord::MONEY_TYPE_USER_OFL_ORDER, + $desc='用户下单(线下)', + $comment='用户下单' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + } + + /** + * @inheritDoc + */ + public function userByOLOrderPaid( + $user_id, + $source_id, + $money, + $user_type=FinancialRecord::USER_TYPE_USER, + $source_type=FinancialRecord::SOURCE_TYPE_ORDER, + $money_type=FinancialRecord::MONEY_TYPE_USER_OL_ORDER, + $desc='用户下单(线上)', + $comment='用户下单' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + } + + /** + * @inheritDoc + */ + public function storeByOLOrderComp( + $user_id, + $source_id, + $money, + $user_type = FinancialRecord::USER_TYPE_STORE, + $source_type = FinancialRecord::SOURCE_TYPE_ORDER, + $money_type = FinancialRecord::MONEY_TYPE_STORE_OL_ORDER_COMP, + $desc = '线上外卖订单收入', + $comment = '用户订单完成' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + // 同时维护钱包 + $store = Store::query()->where(['user_id' => $user_id])->first(); + $store->store_wallet = bcadd($store->store_wallet, $money, 2); + $store->save(); + } + + /** + * @inheritDoc + */ + public function storeByOFLOrderComp( + $user_id, + $source_id, + $money, + $user_type = FinancialRecord::USER_TYPE_STORE, + $source_type = FinancialRecord::SOURCE_TYPE_ORDER, + $money_type = FinancialRecord::MONEY_TYPE_STORE_OFL_ORDER_COMP, + $desc = '线下当面付订单收入', + $comment = '用户订单完成' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + } + + /** + * @inheritDoc + * 订单退款(线上) + */ + public function userByOLOrderRefund( + $user_id, + $source_id, + $money, + $user_type = FinancialRecord::USER_TYPE_USER, + $source_type = FinancialRecord::SOURCE_TYPE_ORDER, + $money_type = FinancialRecord::MONEY_TYPE_USER_OL_ORDER_REFUND, + $desc = '线上订单退款', + $comment = '线上订单退款到微信' + ) + { + $this->recordAll($user_id, $source_id, $money, $user_type, $source_type, $money_type, $desc, $comment); + } +} \ No newline at end of file diff --git a/app/Service/FinancialRecordServiceInterface.php b/app/Service/FinancialRecordServiceInterface.php new file mode 100644 index 0000000..6c71e5b --- /dev/null +++ b/app/Service/FinancialRecordServiceInterface.php @@ -0,0 +1,252 @@ + '', 'pagepath' => '']) { + if (empty($openid) || empty($template_id) || empty($data)) { + return ; + } + // 先拼个基础的 $template = [ 'touser' => $openid, diff --git a/app/Service/OrderService.php b/app/Service/OrderService.php index 3eab4a9..1df6f94 100644 --- a/app/Service/OrderService.php +++ b/app/Service/OrderService.php @@ -5,19 +5,26 @@ namespace App\Service; use App\Commons\Log; use App\Constants\LogLabel; use App\Model\Coupon; -use App\Model\CouponUserRec; +use App\Model\CouponRec; use App\Model\CouponUserUse; use App\Model\Goods; +use App\Model\Market; use App\Model\Order; use App\Model\OrderGoods; use App\Model\OrderMain; +use App\Model\OrderSalesStatistic; use App\Model\SpecCombination; -use App\Model\Users; +use App\Model\Store; use Exception; use Hyperf\DbConnection\Db; use Hyperf\Snowflake\IdGeneratorInterface; use Hyperf\Utils\ApplicationContext; use Hyperf\Di\Annotation\Inject; +use App\Service\WxRefundServiceInterface; +use App\Service\UserServiceInterface; +use App\Model\Users; +use App\Constants\SsdbKeysPrefix; +use App\Service\PurchaseLimitServiceInterface; class OrderService implements OrderServiceInterface { @@ -33,6 +40,36 @@ class OrderService implements OrderServiceInterface */ protected $couponService; + /** + * @Inject + * @var WxRefundServiceInterface + */ + protected $wxRefundService; + + /** + * @Inject + * @var UserServiceInterface + */ + protected $userService; + + /** + * @Inject + * @var PurchaseLimitServiceInterface + */ + protected $purchaseLimitService; + + /** + * @Inject + * @var FinancialRecordServiceInterface + */ + protected $financialService; + + /** + * @Inject + * @var AttachmentServiceInterface + */ + protected $attachmentService; + /** * @inheritDoc */ @@ -40,17 +77,14 @@ class OrderService implements OrderServiceInterface { bcscale(6); - - // 订单判重 $dataMain = $data; - if ($orderMainId = $this->existsByOrderNum($data['order_num'])) { - return $orderMainId; - } - Db::beginTransaction(); try { + // TODO 这个字段后续可能不用了,之前由达达订单号从前端传上来 + $dataMain['order_num'] = 'o'.date('YmdHis').mt_rand(1000,9999); + // 计算当前订单可用红包优惠金额 $couponMoney = 0; $receiveCouponIds = []; @@ -92,16 +126,17 @@ class OrderService implements OrderServiceInterface // 统计订单中所有店铺当日订单数,做店铺订单序号 $countsArr = Order::query() - ->selectRaw('id, COUNT(*) AS count') + ->selectRaw('store_id, COUNT(*) AS count') ->whereIn('store_id', explode(',', $dataMain['store_ids'])) ->where(['type' => OrderMain::ORDER_TYPE_ONLINE]) ->whereBetween('time', [date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')]) + ->groupBy('store_id') ->get() ->toArray(); $storeOrderCounts = []; foreach ($countsArr as $key => &$row) { - $storeOrderCounts[$row['id']] = $row['count']; + $storeOrderCounts[$row['store_id']] = $row['count']; } // 循环处理订单总额、子订单总额、商品、商户订单等信息 @@ -271,6 +306,15 @@ class OrderService implements OrderServiceInterface Db::rollBack(); return '订单商品异常'; } + //判断是否有购买多个特价商品 + $result = $this->purchaseLimitService->PurchaseLimit($orderGoods); + if(!$result){ + Db::rollBack(); + return '同一个订单不能购买多个特价商品'; + } + + //判断是否有购买特价商品 + $this->purchaseLimitService->ssdbPurchaseRecord($orderGoods,$data['user_id'],$dataMain['global_order_id']); // 修改总订单金额,金额是计算来的 // TODO 这部分其实可以结合处理优化一下,循环前后关联处理太多 @@ -281,7 +325,7 @@ class OrderService implements OrderServiceInterface } // 处理红包的使用 - $canUseCoupons = CouponUserRec::select(['id', 'user_id', 'number', 'number_remain', 'system_coupon_user_id']) + $canUseCoupons = CouponRec::select(['id', 'user_id', 'number', 'number_remain', 'system_coupon_user_id']) ->whereIn('id', $receiveCouponIds) ->get()->toArray(); if (is_array($canUseCoupons)&&!empty($canUseCoupons)) { @@ -299,7 +343,6 @@ class OrderService implements OrderServiceInterface 'status' => 1, 'update_time' => 0, ]; - var_dump('$couponUse',$couponUse); $insertRes = CouponUserUse::query()->insert($couponUse); @@ -313,7 +356,7 @@ class OrderService implements OrderServiceInterface $status = 0; } - $upRes = CouponUserRec::query()->where(['id' => $coupon['id']])->update(['number_remain' => $numberRemain, 'status' => $status]); + $upRes = CouponRec::query()->where(['id' => $coupon['id']])->update(['number_remain' => $numberRemain, 'status' => $status]); if (!$upRes) { Db::rollBack(); @@ -403,7 +446,7 @@ class OrderService implements OrderServiceInterface 'code' => $globalRrderId, 'jj_note' => '', 'uniacid' => 2, - 'order_num' => 'dm'.date('YmdHis', time()) . rand(1111, 9999), + 'order_num' => 'dm'.date('YmdHis') . mt_rand(1000, 9999), 'money' => $data['money'], 'user_id' => $data['user_id'], 'store_ids' => $data['store_id'], @@ -417,7 +460,7 @@ class OrderService implements OrderServiceInterface // 子订单模型保存 $dataChild = [ 'uniacid' => 1, - 'order_num' => 's'.date('YmdHis', time()) . rand(1111, 9999), + 'order_num' => 's'.date('YmdHis') . mt_rand(1000, 9999), 'user_id' => $orderMain->user_id, 'store_id' => $data['store_id'], 'order_main_id' => $orderMainId, @@ -465,14 +508,13 @@ class OrderService implements OrderServiceInterface } } - - /** * 计算和校验当前订单可用红包及金额 * @param $couponIds * @param $orderAmount * @param $userId * @param $marketId + * @return int|string * @throws Exception */ protected function getCouponAmount($couponIds, $orderAmount, $userId, $marketId) @@ -525,12 +567,421 @@ class OrderService implements OrderServiceInterface } /** - * 订单是否存在 - * @param $orderNum - * @return \Hyperf\Utils\HigherOrderTapProxy|mixed|void|null + * @inheritDoc + */ + public function existsByGlobalOrderId($global_order_id) + { + return OrderMain::query()->where(['order_num' => $global_order_id])->value('id'); + } + + /** + * @inheritDoc + */ + public function onlineCompleted($global_order_id) + { + Db::beginTransaction(); + try { + + // 主订单状态更新 + $orderMain = OrderMain::query() + ->where(['global_order_id' => $global_order_id, 'state' => OrderMain::ORDER_STATE_DELIVERY]) + ->first(); + + if (empty($orderMain)) { + Db::rollBack(); + return false; + } + + $orderMain->state = OrderMain::ORDER_STATE_COMPLETE; + $orderMain->save(); + + // 子订单状态更新 + $upChild = Order::query() + ->where(['order_main_id' => $orderMain->id]) + ->update(['state' => OrderMain::ORDER_STATE_COMPLETE]); + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::ONLINE_COMPLETE_LOG, ['exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + + } + + /** + * @inheritDoc */ - public function existsByOrderNum($orderNum) + public function onlinePaid($global_order_id) { - return OrderMain::query()->where(['order_num' => $orderNum])->value('id'); + Db::beginTransaction(); + try { + // 查询订单 + $orderMain = OrderMain::query() + ->where([ + 'global_order_id' => $global_order_id, + 'type' => OrderMain::ORDER_TYPE_ONLINE + ]) + ->first(); + + // 修改订单、子订单状态 + $currentTime = time(); + $orderMain->state = OrderMain::ORDER_STATE_UNTAKE; + $orderMain->time_pay = $currentTime; + $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime); + $orderMain->save(); + + $upOrder = Order::query() + ->where(['order_main_id' => $orderMain->id]) + ->update(['state' => OrderMain::ORDER_STATE_UNTAKE, 'pay_time' => $orderMain->pay_time]); + + // 更新商户销量 + $upStoreScore = Store::query() + ->whereIn('id', explode(',', $orderMain->store_ids)) + ->update(['score' => Db::raw('score+1')]); + + // 更新商品库存和销量 + $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) + ->where(['order_main_id' => $orderMain->id]) + ->get() + ->toArray(); + $orderGoods = OrderGoods::query()->select(['good_id AS id', 'number', 'combination_id']) + ->whereIn('order_id', array_values(array_column($orders, 'id'))) + ->get() + ->toArray(); + foreach ($orderGoods as $key => &$goodsItem) { + + $goods = Goods::find($goodsItem['id']); + + // 库存处理,有规格 + if ($goodsItem['combination_id']) { + $combination = SpecCombination::find($goodsItem['combination_id']); + $combination->number = $combination->number - $goodsItem['number']; + $combination->save(); + } else { + $goods->inventory = $goods->inventory - $goodsItem['number']; + } + + $goods->sales = $goods->sales - $goodsItem['number']; + $goods->save(); + + } + + // 月销流水 + $statistics = []; + foreach ($orders as $key => &$order) { + $statistics[] = [ + 'money' => $order['money'], + 'user_id' => $order['user_id'], + 'store_id' => $order['store_id'], + 'market_id' => $orderMain->market_id, + 'order_id' => $order['id'], + 'createtime' => strtotime($order['pay_time']), + ]; + } + + if (is_array($statistics) && !empty($statistics)) { + $inSalesStatistics = OrderSalesStatistic::query()->insert($statistics); + } + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::ONLINE_PAID_LOG, ['exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + } + + /** + * @inheritDoc + */ + public function offlinePaid($global_order_id) + { + Db::beginTransaction(); + try { + + // 主订单状态更新 + $orderMain = OrderMain::query() + ->where(['global_order_id' => $global_order_id, 'type' => OrderMain::ORDER_TYPE_OFFLINE]) + ->first(); + + if (empty($orderMain)) { + + $this->log->event( + LogLabel::PAY_NOTIFY_WXMINI, + ['order_not_found' => $global_order_id] + ); + Db::rollBack(); + return false; + } + + $currentTime = time(); + $orderMain->state = OrderMain::ORDER_STATE_UNTAKE; + $orderMain->dm_state = OrderMain::ORDER_STATE_UNTAKE; + $orderMain->time_pay = $currentTime; + $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime); + $orderMain->save(); + + // 子订单状态更新 + $upOrder = Order::query() + ->where(['order_main_id' => $orderMain->id]) + ->update([ + 'state' => OrderMain::ORDER_STATE_UNTAKE, + 'dm_state' => OrderMain::ORDER_STATE_UNTAKE, + 'pay_time' => date('Y-m-d H:i:s', $currentTime) + ]); + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::OFFLINE_PAID_LOG, ['exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + } + + /** + * @inheritDoc + */ + public function onlineCancel($global_order_id){ + $sqlRes = OrderMain::where('global_order_id',$global_order_id) + ->update(['state' => OrderMain::ORDER_STATE_CANCEL]); + if(!$sqlRes){ + return false; + } + //撤销redis 用券记录 + $redisRes = $this->couponService->orderRefundCoupons($global_order_id); + //撤销特价商品购买记录 + $ssdbRes = $this->purchaseLimitService->delSsdbPurchaseRecord($global_order_id); + return $redisRes && $ssdbRes; + } + /** + * @inheritDoc + */ + public function onlineRefund($global_order_id) + { + Db::beginTransaction(); + try { + // 主订单状态更新 + $orderMain = OrderMain::query() + ->select('id','global_order_id','state','pay_type','user_id','money') + ->where(['global_order_id' => $global_order_id, 'state' => OrderMain::ORDER_STATE_REFUNDING]) + ->first(); + + if (empty($orderMain)) { + Db::rollBack(); + return [ + 'code' => 1, + 'msg' =>'查询不到订单' + ]; + } + + $orderMain->state = OrderMain::ORDER_STATE_REFUNDED; + + if(!$orderMain->save()){ + Db::rollBack(); + return [ + 'code' => 2, + 'msg' =>'更新主订单失败' + ]; + }; + + // 子订单状态更新 + $upChild = Order::query() + ->where('order_main_id' , $orderMain->id) + ->where('state',OrderMain::ORDER_STATE_REFUNDING) + ->update(['state' => OrderMain::ORDER_STATE_REFUNDED]); + if(empty($upChild)){ + Db::rollBack(); + return [ + 'code' => 3, + 'msg' =>'更新子订单失败' + ]; + } + + if($orderMain->pay_type == OrderMain::ORDER_PAY_WX){ + + // 微信支付 微信退款 + $refundRes = $this->wxRefundService->wxPayRefund($orderMain->global_order_id); + if( + empty($refundRes) + || !$refundRes + || !isset($refundRes['result_code']) + || $refundRes['result_code'] != 'SUCCESS' + ){ + Db::rollBack(); + return $refundRes; + }; + }else if($orderMain->pay_type == OrderMain::ORDER_PAY_BALANCE){ + + // 余额支付 退款到用户余额 + if($this->userService->userWallet($orderMain->user_id,$orderMain->money,Users::WALLET_TYPE_INC)){ + Db::rollBack(); + return [ + 'code' => 4, + 'msg' =>'退款到用户余额失败' + ]; + }; + } + + /* --- 退款成功 --- */ + $orderMain = $orderMain->fresh(); + if(empty($orderMain->refund_time)){ + // 添加退款时间 + $orderMain->refund_time = time(); + $orderMain->save(); + + // 退款返还优惠券 + $this->couponService->orderRefundCoupons($orderMain->global_order_id); + + // 删除特价商品缓存 + $this->purchaseLimitService->delSsdbPurchaseRecord($orderMain->global_order_id); + + // 添加用户的流水 + $this->financialService->userByOLOrderRefund($orderMain->user_id, $orderMain->global_order_id, $orderMain->money); + } + + Db::commit(); + return [ + 'code' => 0, + 'msg' =>'退款成功' + ]; + } catch (\Exception $e) { + + $this->log->event(LogLabel::ORDER_LOG, ['msg'=> '订单退款','exception' => $e->getMessage()]); + Db::rollBack(); + return [ + 'code' => 5, + 'msg' => $e->getMessage() + ]; + } + } + + /** + * 订单退款失败 + * 回退订单状态 + */ + public function onlineRefundFail($global_order_id) + { + Db::beginTransaction(); + try { + + $time = time(); + // 主订单状态更新 + $orderMain = OrderMain::query() + ->select('id','global_order_id','state','pay_type') + ->where(['global_order_id' => $global_order_id, 'state' => OrderMain::ORDER_STATE_REFUNDED]) + ->first(); + + if (empty($orderMain)) { + Db::rollBack(); + return false; + } + + $orderMain->state = OrderMain::ORDER_STATE_REFUNDING; + $upOrderMain = $orderMain->save(); + + // 子订单状态更新 + $upChild = Order::query() + ->where('order_main_id' , $orderMain->id) + ->where('state',OrderMain::ORDER_STATE_REFUNDED) + ->update(['state' => OrderMain::ORDER_STATE_REFUNDING]); + if(empty($upChild)){ + Db::rollBack(); + return false; + } + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::ORDER_LOG, ['msg'=> '订单退款失败时处理状态9->8 ','exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + } + + /** + * 删除特价商品缓存 + */ + public function clearTodayGoodPurchase($userId, $goodId) + { + $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); + return $ssdb->exec('del', SsdbKeysPrefix::PURCHASE_RECORD. date('Ymd') .'_'.$userId, $goodId); + } + + /** + * @inheritDoc + */ + public function onlineAutoCancelByUserId($user_id) + { + Db::beginTransaction(); + try { + + $orders = OrderMain::query() + ->select(['id', 'global_order_id']) + ->where([ + 'user_id' => $user_id, + 'state' => OrderMain::ORDER_STATE_UNPAY + ]) + ->where('time_add', '<', (time()-900)) + ->get()->toArray(); + + foreach ($orders as $key => &$item) { + $order = OrderMain::query()->find($item['id']); + $order->state = OrderMain::ORDER_STATE_CANCEL; + $order->save(); + //撤销redis 用券记录 + $this->couponService->orderRefundCoupons($item['global_order_id']); + //撤销特价商品购买记录 + $this->purchaseLimitService->delSsdbPurchaseRecord($item['global_order_id']); + } + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::AUTO_CANCEL_USER_ORDER, ['exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + + } + + /** + * @inheritDoc + */ + public function userOnlineOrders($user_id, $state, $page=1, $pagesize=10) + { + $builder = OrderMain::query() + ->where(['user_id' => $user_id, 'del' => OrderMain::ORDER_DEL_NO, 'type' => OrderMain::ORDER_TYPE_ONLINE]); + if ($state != 0) { + $state = explode(',', $state); + $builder = $builder->whereIn('state', $state); + } + $orders = $builder->orderBy('id', 'desc') + ->orderBy('state', 'asc') + ->get()->forPage($page, $pagesize)->toArray(); + + foreach ($orders as $key => &$order) { + // 市场名称 + $order['market_name'] = Market::query()->where(['id' => $order['market_id']])->value('name'); + + // 商品数量和第一个商品名、图 + $orderChildIds = Order::query()->select(['id'])->where(['order_main_id' => $order['id']])->get()->toArray(); + $orderChildIds = array_values(array_column($orderChildIds, 'id')); + $order['g_num'] = OrderGoods::query()->whereIn('order_id', $orderChildIds)->count(); + $goods = OrderGoods::query()->whereIn('order_id', $orderChildIds)->select(['name', 'img'])->first(); + $order['good_name'] = $goods->name; + // TODO 临时写死oss压缩类型 + $order['img'] = $this->attachmentService->switchImgToAliOss($goods->img); + } + + return $orders; } } \ No newline at end of file diff --git a/app/Service/OrderServiceInterface.php b/app/Service/OrderServiceInterface.php index 0d5e0a2..87990eb 100644 --- a/app/Service/OrderServiceInterface.php +++ b/app/Service/OrderServiceInterface.php @@ -15,15 +15,78 @@ interface OrderServiceInterface /** * 线下订单下单 * 扫码支付 + * @param $data * @return mixed */ public function addOfflineOrder($data); /** * 订单是否已经存在 - * @param $orderNum + * @param $global_order_id + * @return mixed + */ + public function existsByGlobalOrderId($global_order_id); + + /** + * 订单完成 + * @param $global_order_id + * @return mixed + */ + public function onlineCompleted($global_order_id); + + /** + * 线上订单支付完成 + * @param $global_order_id + * @return mixed + */ + public function onlinePaid($global_order_id); + + /** + * 线下订单支付完成 + * @param $global_order_id + * @return mixed + */ + public function offlinePaid($global_order_id); + + /** + * 线上订单取消 + * @param $global_order_id + * @return mixed + */ + public function onlineCancel($global_order_id); + + /** + * 线上订单退款 + * @param $global_order_id * @return mixed + */ + public function onlineRefund($global_order_id); + + /** + * 订单退款失败 + * 回退订单状态 + */ + public function onlineRefundFail($global_order_id); + + /** + * 删除特价商品缓存 + */ + public function clearTodayGoodPurchase($userId, $goodId); + + /** + * 自动取消订单 + * 用户待付款订单超时15分钟未付款 + * @param $user_id */ - public function existsByOrderNum($orderNum); + public function onlineAutoCancelByUserId($user_id); + /** + * 用户订单 + * @param $user_id + * @param $state + * @param int $page + * @param int $pagesize + * @return mixed + */ + public function userOnlineOrders($user_id, $state, $page=1, $pagesize=10); } \ No newline at end of file diff --git a/app/Service/PurchaseLimitService.php b/app/Service/PurchaseLimitService.php new file mode 100644 index 0000000..5fe5f02 --- /dev/null +++ b/app/Service/PurchaseLimitService.php @@ -0,0 +1,104 @@ + 7, + // 'item' => 1, + // 'item_text' => 'page', + // 'logo' => 'http://lanzutest.lanzulive.com/attachment/images/2/2020/08/PY55Y3Mz17yJo17rv1Z7vImX1V5159.jpg', + // 'redirect_url' => '/zh_cjdianc/pages/takeout/takeoutindex?storeid=123', + // 'src' => '/zh_cjdianc/pages/takeout/takeoutindex?storeid=123', + // 'src2' => '/zh_cjdianc/pages/takeout/takeoutindex?storeid=123', + // ]; + // $res[] = [ + // 'id' => 8, + // 'item' => 1, + // 'item_text' => 'page', + // 'logo' => 'http://lanzutest.lanzulive.com/attachment/images/2/2020/08/PY55Y3Mz17yJo17rv1Z7vImX1V5159.jpg', + // 'redirect_url' => '/zh_cjdianc/pages/takeout/takeoutindex?storeid=109', + // 'src' => '/zh_cjdianc/pages/takeout/takeoutindex?storeid=109', + // 'src2' => '/zh_cjdianc/pages/takeout/takeoutindex?storeid=109', + // ]; + return ''; + } + + public function ssdbPurchaseRecord($data,$user_id,$global_order_id) + { + foreach ($data as $k => $v){ + if($v['money'] == 0.01){ + //添加特价商品购买记录到ssdb + $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); + $ssdb->exec('set', SsdbKeysPrefix::PURCHASE_RECORD. date('Ymd') .'_'.$user_id.'_'.$v['good_id'], $global_order_id); + $end_timestamp = strtotime(date('Y-m-d').'23:59:59'); + $end_time = $end_timestamp - time(); + $ssdb->exec('expire', SsdbKeysPrefix::PURCHASE_RECORD. date('Ymd') .'_'.$user_id.'_'.$v['good_id'],$end_time); + } + } + return true; + } + + public function delSsdbPurchaseRecord($global_order_id) + { + $order_main = OrderMain::where('global_order_id',$global_order_id) + ->select('id','user_id') + ->first(); + + $order_id = $order_main->id; + + $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); + $order = Order::query() + ->where('order_main_id',$order_id) + ->select('id','user_id') + ->get() + ->toArray(); + foreach ($order as $k1 => $v1){ + $goods = OrderGoods::query() + ->where([ + ['order_id','=',$v1['id']], + ['money','=',0.01], + ]) + ->select('good_id') + ->get() + ->toArray(); + + foreach ($goods as $k2 => $v2) { + $ssdb->exec('del', SsdbKeysPrefix::PURCHASE_RECORD. date('Ymd') .'_'.$v1['user_id'].'_'.$v2['good_id']); + } + } + return true; + } + + public function PurchaseLimit($orderGoods) + { + $sum = 0; + foreach ($orderGoods as $goods){ + if($goods['money'] == 0.01){ + if($sum > 0){ + return false; + } + $sum++; + } + } + return true; + } + +} \ No newline at end of file diff --git a/app/Service/PurchaseLimitServiceInterface.php b/app/Service/PurchaseLimitServiceInterface.php new file mode 100644 index 0000000..9ff3184 --- /dev/null +++ b/app/Service/PurchaseLimitServiceInterface.php @@ -0,0 +1,17 @@ +where(['global_order_id' => $global_order_id]) + ->first(); + + if (empty($orderMain)) { + return false; + } + + // =======用户支付流水 / Start======= + $this->financialRecordService->userByOLOrderPaid($orderMain->user_id, $global_order_id, $orderMain->money); + // =======用户支付流水 / End======= + } + + /** + * @inheritDoc + */ + public function orderOnlineCompleted($global_order_id) + { + // 线上订单完成(用户点击确认收货完成/管理后台点击完成/配送员点击完成/自动收货等),进行相关分账 + // 订单 + $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; + } + + $currentTime = time(); + Db::beginTransaction(); + try { + + // =======商户订单收入流水 / Start======= + // 查询子订单 + $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) + ->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']); + } + // =======商户订单收入流水 / End======= + + // =======社区服务点分账 / Start======= + // 前提:用户线上下单并且订单完成 + // 奖励规则A:用户是平台新用户,奖励社区服务点平台新用户奖励x元+平台新用户首单奖励y元+订单商品金额z%的分成 + // 奖励规则B:用户是非新用户,奖励社区服务点订单实际支付金额z%的分成 + // =======社区服务点分账 / Start======= + + // 当前用户的社区服务点绑定关系 + $communityBind = UserRelationBind::query() + ->where(['bind_type' => UserRelationBind::BIND_TYPE_COMMUNITY, 'user_id' => $orderMain->user_id]) + ->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']); + } + + // 账单分成 + $money = bcmul($orderMain->money, bcdiv($award['flow_reward'], 100, 6), 2); + $this->financialRecordService->communitySeparateAccountsByOrderComp($communityBind->source_id, $global_order_id, $money); + } + + // =======社区服务点分账 / End======= + + Db::commit(); + return true; + + } catch (\Exception $e) { + + $this->log->event(LogLabel::SEPARATE_ACCOUNTS_LOG, ['exception' => $e->getMessage(), 'order_main' => json_encode($orderMain)]); + Db::rollBack(); + return false; + } + + } + + /** + * @inheritDoc + */ + public function orderOfflinePaid($global_order_id) + { + // 线下订单支付完成 + // 订单 + $orderMain = OrderMain::query() + ->where(['global_order_id' => $global_order_id]) + ->first(); + + if (empty($orderMain)) { + return false; + } + + // 查询子订单,当面付目前实际上只有一个子订单 + $order = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time']) + ->where(['order_main_id' => $orderMain->id]) + ->first(); + + if (empty($order)) { + return false; + } + + $currentTime = time(); + Db::beginTransaction(); + try { + + // =======用户支付流水 / Start======= + $this->financialRecordService->userByOFLOrderPaid($orderMain->user_id, $global_order_id, $orderMain->money); + // =======用户支付流水 / End======= + + // =======线下订单支付完成商户分账 / Start======= + // 前提:用户线上下单并且支付完成 + // 奖励规则A:用户是平台新用户,奖励商户2元 + // 奖励规则B:用户是非新用户,但是是商户当日首单,奖励商户0.05元 + // =======线下订单支付完成商户分账 / Start======= + + // 旧商户订单流水基础数据 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' => 2, + ]; + StoreAccount::query()->insert(array_merge($storeAccountBase, $storeAccount)); + + // 商户 + $store = Store::find($order->store_id); + + // 新商户订单流水 + $this->financialRecordService->storeByOFLOrderComp($store->user_id, $global_order_id, $order->money); + + $needAward = false; + $awardAmount = 0; + // 新用户商户奖励 + if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->id)) { + + $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_new_user'])->value('value'); + // 旧商户流水 TODO 直接移除或后续考虑移除 + $storeAccount = [ + 'money' => $awardAmount, + 'note' => '新用户下单成功,平台奖励', + 'category' => 3, + ]; + // 新商户流水 + $this->financialRecordService->storeAwardByPlatNewUserOFLOrder($store->user_id, $global_order_id, $awardAmount); + $needAward = true; + + } else { + // 商户当日首单奖励 + if ( + $this->userService->isStoreFirstOrderToday( + $order->user_id, + $order->store_id, + $order->id, + FinancialRecord::OFL_FIRST_AWARD_LIMIT_AMOUNT + ) + && $order->money >= FinancialRecord::OFL_FIRST_AWARD_LIMIT_AMOUNT + ) { + + $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_each_order'])->value('value'); + // 旧商户流水 TODO 直接移除或后续考虑移除 + $storeAccount = [ + 'money' => $awardAmount, + 'note' => '用户下单成功,平台奖励', + 'category' => 4, + ]; + // 新商户流水 + $this->financialRecordService->storeAwardByTodayFirstOFLOrder($store->user_id, $global_order_id, $awardAmount); + $needAward = true; + + } + } + + if ($needAward && $awardAmount) { + + // 旧商户流水 TODO 直接移除或后续考虑移除 + StoreAccount::query()->insert(array_merge($storeAccountBase, $storeAccount)); + + // 发模板消息 + $openid = Users::query()->where(['id' => $store['user_id']])->value('openid'); + $res = $this->miniprogramService->sendTemMsgForAward($storeAccount['money'], $storeAccount['note'], $openid, $storeAccountBase['time']); + } + + // =======线下订单支付完成商户分账 / End======= + + Db::commit(); + return true; + } catch (\Exception $e) { + + $this->log->event(LogLabel::SEPARATE_ACCOUNTS_LOG, ['exception' => $e->getMessage(), 'order_main' => json_encode($orderMain)]); + Db::rollBack(); + return false; + } + } +} \ No newline at end of file diff --git a/app/Service/SeparateAccountsServiceInterface.php b/app/Service/SeparateAccountsServiceInterface.php new file mode 100644 index 0000000..c574735 --- /dev/null +++ b/app/Service/SeparateAccountsServiceInterface.php @@ -0,0 +1,28 @@ +get(SSDBTask::class); + $record_exists = $ssdb->exec('get',SsdbKeysPrefix::PURCHASE_RECORD. date('Ymd') .'_'.$params['user_id'].'_'.$params['good_id']); + if($record_exists) + { + $error = [ + 'error' => '特价商品每日只能购买一次' + ]; + return $error; + } + //一个订单只能添加一个特价商品 + if($params['money'] == 0.01){ + $goods_exists = ShopCar::where([ + ['user_id','=',$params['user_id']], + ['good_id','!=',$params['good_id']], + ['market_id','=',$params['market_id']], + ['money','=',0.01] + ]) + ->exists(); + if($goods_exists){ + $error = [ + 'error' => '一个订单只能添加一个特价商品' + ]; + return $error; + } + } + //获取主表商品表信息 + $goods = Goods::where([ + ['id','=',$params['good_id']], + ]) + ->select('is_max','restrict_num','box_money','inventory','money') + ->first(); + + //获取购物车该商品购买数量 + $num = ShopCar::where([ + ['user_id', $params['user_id']], + ['good_id', $params['good_id']], + ]) + ->sum('num'); + //限购检验 + if($goods->restrict_num > 0 && $goods->restrict_num <= $num) + { + $error = [ + 'error' => '超过商品限购数量' + ]; + return $error; + } + //获取规格表商品信息 + if($params['combination_id'] > 0) + { + $combination = Combination::where([ + ['id', '=', $params['combination_id']], + ]) + ->select('wm_money', 'number') + ->first(); + $inventory = $combination->number; + $money = $combination->wm_money; + }else{ + $inventory = $goods->inventory; + $money = $goods->money; + } + //库存校验 is_max 无限库存 + if($goods->is_max != Goods::INVENTORY_NOLIMIT && ($num + $params['num']) > $inventory) + { + $error = [ + 'error' => '库存不足' + ]; + return $error; + } + //更新购物车 + $exists_sql = ShopCar::where([ + ['user_id', '=', $params['user_id']], + ['good_id', '=', $params['good_id']], + ['market_id','=',$params['market_id']], + ['combination_id','=', $params['combination_id']], + ]); + if($params['combination_id'] > 0) { + $exists_sql->where('combination_id',$params['combination_id']); + } + $exists = $exists_sql->exists(); + if($exists) + { + $update = ShopCar::where([ + ['user_id', '=', $params['user_id']], + ['good_id', '=', $params['good_id']], + ['market_id','=',$params['market_id']], + ]); + if($params['combination_id'] > 0) { + $update->where('combination_id',$params['combination_id']); + } + $update->increment('num', $params['num']); + }else{ + $son_id = empty($params['son_id']) ? 0 : $params['son_id']; + $dr_id = empty($params['dr_id']) ? 0 : $params['dr_id']; + $combination_id = empty($params['combination_id']) ? 0 : $params['combination_id']; + $qg_name = empty($params['qg_name']) ? ' ' : $params['qg_name']; + $qg_logo = empty($params['qg_logo']) ? ' ' :$params['qg_logo']; + ShopCar::insert( + [ + 'market_id' => $params['market_id'], + 'good_id' => $params['good_id'], + 'store_id' => $params['store_id'], + 'user_id' => $params['user_id'], + 'combination_id' => $combination_id, + 'num' => $params['num'], + 'spec' => $params['spec'], + 'son_id' => $son_id, + 'dr_id' => $dr_id, + 'qg_name' => $qg_name, + 'qg_logo' => $qg_logo, + 'money' => $money, + 'box_money' => $goods->box_money, + ] + ); + } + return true; + // if($params['goods_id'] == 1561){ + // return false; + // }else{ + // return '加入购物车成功'; + // } + } + + public function updateShopCar($params) + { + if($params['num'] <= 0) + { + ShopCar::where('id',$params['id'])->delete(); + }else { + $shop_car = ShopCar::where('id',$params['id']) + ->select('good_id','user_id') + ->first(); + //获取主表商品表信息 + $goods = Goods::where([ + ['id','=',$shop_car['good_id']], + ]) + ->select('is_max','restrict_num','box_money','inventory','money') + ->first(); + //获取购物车该商品购买数量 + $num = ShopCar::where([ + ['user_id', $shop_car['user_id']], + ['good_id', $shop_car['good_id']], + ]) + ->sum('num'); + //限购检验 + if($goods->restrict_num > 0 && $goods->restrict_num <= $num) + { + $error = [ + 'error' => '超过商品限购数量' + ]; + return $error; + } + if ($shop_car['combination_id'] > 0) + { + $combination = Combination::where([ + ['id', '=', $shop_car['combination_id']], + ]) + ->select('wm_money', 'number') + ->first(); + $inventory = $combination->number; + }else{ + $inventory = $goods->inventory; + } + //库存校验 is_max 无限库存 + if($goods->is_max != Goods::INVENTORY_NOLIMIT && $params['num'] > $inventory) + { + $error = [ + 'error' => '库存不足' + ]; + return $error; + } + ShopCar::where('id',$params['id']) + ->update(['num' => $params['num']]); + return true; + } + // if($params['good_id'] == 1561){ + // return false; + // }else{ + // return '更新购物车成功'; + // } + } +} \ No newline at end of file diff --git a/app/Service/ShopCarServiceInterface.php b/app/Service/ShopCarServiceInterface.php new file mode 100644 index 0000000..7691a71 --- /dev/null +++ b/app/Service/ShopCarServiceInterface.php @@ -0,0 +1,12 @@ +regionId($alisms['regionid']) + ->asDefaultClient(); + + try { + $result = AlibabaCloud::rpc() + ->product($alisms['product']) + // ->scheme('https') // https | http + ->version('2017-05-25') + ->action('SendSms') + ->method('POST') + ->host($alisms['host']) + ->options([ + 'query' => [ + 'RegionId' => $alisms['regionid'], + 'PhoneNumbers' => $phone, + 'SignName' => $signName, + 'TemplateCode' => $template, + 'TemplateParam' => $templateParams, + ], + ]) + ->request(); + return $result->toArray(); + } catch (ClientException $e) { + $this->log->event('alisms', ['alisms_error_ClientException' => $e->getErrorMessage()]); + return false; + } catch (ServerException $e) { + $this->log->event('alisms', ['alisms_error_ServerException' => $e->getErrorMessage()]); + return false; + } + } + + public function sendForCommunityFinancial($userId, $money) + { + + $csInfo = CsInfo::query()->where(['admin_user_id' => $userId])->first(); + $market = Market::query()->where(['id' => $csInfo->market_id])->first(); + + $params = ['user_name' => $csInfo->name, 'market_name' => $market->name, 'money' => $money]; + return $this->send($csInfo->phone, self::TEMPLATE_COMMUNITY_FINANCIAL, json_encode($params)); + } +} \ No newline at end of file diff --git a/app/Service/SmsServiceInterface.php b/app/Service/SmsServiceInterface.php new file mode 100644 index 0000000..7f69282 --- /dev/null +++ b/app/Service/SmsServiceInterface.php @@ -0,0 +1,9 @@ +updateOrCreate( + ['bind_type' => $bind_type, 'user_id' => $user_id], + ['source_id' => $source_id, 'json_data' => $extra_data] + ); + } + + public function bindLimitBySource($bind_type, $source_id, $user_id, $extra_data) + { + // TODO: Implement bindLimitBySource() method. + } + + public function bind($bind_type, $source_id, $user_id, $extra_data) + { + // TODO: Implement bind() method. + } + + public function isBinded($bind_type, $source_id, $user_id) + { + // TODO: Implement isBinded() method. + } +} \ No newline at end of file diff --git a/app/Service/UserRelationBindServiceInterface.php b/app/Service/UserRelationBindServiceInterface.php new file mode 100644 index 0000000..33eccc3 --- /dev/null +++ b/app/Service/UserRelationBindServiceInterface.php @@ -0,0 +1,48 @@ +where(['user_id' => $user_id]) @@ -76,4 +76,23 @@ class UserService implements UserServiceInterface ->where('id', '!=', $current_order_id) ->exists(); } + + /** + * 用户账户(钱包) + * @inheritDoc + * $type 1增 2减 + */ + public function userWallet($userId,$money,$type) + { + $user = Users::select('id','wallet')->where('id',$userId)->lockForUpdate()->first(); + $res = false; + if(!empty($user) && is_numeric($money) && $money > 0){ + if($type == Users::WALLET_TYPE_INC){ + $res = $user->increment('wallet',$money); + }else if($type == Users::WALLET_TYPE_DEC){ + $res = $user->decrement('wallet',$money); + } + } + return $res; + } } \ No newline at end of file diff --git a/app/Service/UserServiceInterface.php b/app/Service/UserServiceInterface.php index 2920d53..29c5066 100644 --- a/app/Service/UserServiceInterface.php +++ b/app/Service/UserServiceInterface.php @@ -12,7 +12,7 @@ interface UserServiceInterface * @param $order_main_id * @return mixed */ - public function isStageNewUser($user_id, $order_main_id): bool; + public function isPlatformNewUser($user_id, $order_main_id): bool; public function saveUserUnionid($openid,$unionid); @@ -26,4 +26,13 @@ interface UserServiceInterface */ public function isStoreFirstOrderToday($user_id, $store_id, $current_order_id, $limit_amount = 3); + /** + * 用户账户(钱包) + * @inheritDoc + * @param $userId + * @param $money + * @param $type 1增 2减 + * @return mixed + */ + public function userWallet($userId,$money,$type); } \ No newline at end of file diff --git a/app/Service/WxRefundService.php b/app/Service/WxRefundService.php new file mode 100644 index 0000000..6c7545e --- /dev/null +++ b/app/Service/WxRefundService.php @@ -0,0 +1,68 @@ +select(['id','global_order_id','order_num','money','state']) + ->where('global_order_id',$global_order_id) + ->where('pay_type',OrderMain::ORDER_PAY_WX) + ->whereRaw('refund_time is null') + ->first(); + + if(empty($orderMain)){ + return false; + }; + + $options = [ + 'refund_desc' => '线上订单退款', + // 'notify_url' => config('site_host') . '/wechat/notify/wxpayrefund' + ]; + $result = $app->refund->byOutTradeNumber( + $orderMain->global_order_id, + $orderMain->global_order_id, + $orderMain->money * 100, + $orderMain->money * 100, + $options + ); + } catch (QueryException $e) { + $this->log->event(LogLabel::WX_PAY_REFUND,$e->getMessage()); + return false; + } catch (BusinessException $e){ + $this->log->event(LogLabel::WX_PAY_REFUND,$e->getMessage()); + return false; + } + + $this->log->event(LogLabel::WX_PAY_REFUND,$result); + return $result; + } + +} \ No newline at end of file diff --git a/app/Service/WxRefundServiceInterface.php b/app/Service/WxRefundServiceInterface.php new file mode 100644 index 0000000..096c055 --- /dev/null +++ b/app/Service/WxRefundServiceInterface.php @@ -0,0 +1,8 @@ + \App\Service\MqttSpeakerService::class, \App\Service\FeiePrintServiceInterface::class => \App\Service\FeiePrintService::class, \App\Service\MiniprogramServiceInterface::class => \App\Service\MiniprogramService::class, - \App\Service\UserServiceInterface::class => \App\Service\UserService::class, + \App\Service\PurchaseLimitServiceInterface::class => \App\Service\PurchaseLimitService::class, + \App\Service\UserRelationBindServiceInterface::class => \App\Service\UserCommunityBindService::class, + \Hyperf\JsonRpc\JsonRpcTransporter::class => \Hyperf\JsonRpc\JsonRpcPoolTransporter::class, + \App\JsonRpc\OrderServiceInterface::class => \App\JsonRpc\OrderService::class, + \App\Service\FinancialRecordServiceInterface::class => \App\Service\FinancialRecordService::class, + \App\Service\SeparateAccountsServiceInterface::class => \App\Service\SeparateAccountsService::class, + \App\Service\ShopCarServiceInterface::class => \App\Service\ShopCarService::class, + \App\Service\WxRefundServiceInterface::class => \App\Service\WxRefundService::class, + \App\Service\SmsServiceInterface::class => \App\Service\SmsAliService::class, \App\Service\OrderListServiceInterface::class => \App\Service\OrderListService::class, ]; diff --git a/config/autoload/server.php b/config/autoload/server.php index f44b083..1418f3a 100644 --- a/config/autoload/server.php +++ b/config/autoload/server.php @@ -25,6 +25,16 @@ return [ SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'], ], ], + [ + 'name' => 'jsonrpc-http', + 'type' => Server::SERVER_HTTP, + 'host' => '0.0.0.0', + 'port' => 9505, + 'sock_type' => SWOOLE_SOCK_TCP, + 'callbacks' => [ + SwooleEvent::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'], + ], + ], ], 'settings' => [ 'enable_coroutine' => true, diff --git a/config/config.php b/config/config.php index ba75ad6..d416f7f 100644 --- a/config/config.php +++ b/config/config.php @@ -40,5 +40,12 @@ return [ 'wxtempmsg' => [ 'app_id' => env('APP_ID',''), 'secret' => env('APP_SECRET',''), + ], + 'alisms' => [ + 'app_key' => env('ALI_SMS_APP_KEY', ''), + 'app_secret' => env('ALI_SMS_APP_SECRET', ''), + 'regionid' => env('ALI_SMS_REGION_ID', ''), + 'product' => env('ALI_SMS_PRODUCT', ''), + 'host' => env('ALI_SMS_HOST', ''), ] ]; diff --git a/config/routes.php b/config/routes.php index d3b1568..659680f 100644 --- a/config/routes.php +++ b/config/routes.php @@ -50,16 +50,27 @@ Router::addGroup('/v1/',function (){ //订单相关 Router::post('Order/addOnline', 'App\Controller\OrderController@addOnlineOrder'); Router::post('Order/addOffline', 'App\Controller\OrderController@addOfflineOrder'); + Router::post('Order/onlineCancel', 'App\Controller\OrderController@onlineCancel'); + Router::post('Order/userComp', 'App\Controller\OrderController@userComp'); + Router::post('Order/userOnlineOrders', 'App\Controller\OrderController@userOnlineOrders'); //小程序支付相关 Router::post('wxminipay/online', 'App\Controller\PaymentController@wxminiPayOnline'); Router::post('wxminipay/offline', 'App\Controller\PaymentController@wxminiPayOffline'); - + + //加入购物车 + Router::post('ShopCar/addShopCar', 'App\Controller\ShopCarController@addShopCar'); + Router::post('ShopCar/updateShopCar', 'App\Controller\ShopCarController@updateShopCar'); + + Router::post('PurchaseLimit/delSsdbPurchaseRecord', 'App\Controller\PurchaseLimitController@delSsdbPurchaseRecord'); + Router::post('PurchaseLimit/getStoreIdByMarketId', 'App\Controller\PurchaseLimitController@getStoreIdByMarketId'); Router::post('OrderList/storeOrderList', 'App\Controller\OrderListController@storeOrderList'); Router::post('OrderList/userOrderList', 'App\Controller\OrderListController@userOrderList'); + },['middleware' => [\App\Middleware\Auth\ApiMiddleware::class]]); Router::addGroup('/wechat/',function () { Router::post('notify/wxminionline', 'App\Controller\NotifyController@wxminiOnline'); Router::post('notify/wxminioffline', 'App\Controller\NotifyController@wxminiOffline'); + Router::post('notify/wxpayrefund', 'App\Controller\NotifyPayRefundController@wxPayRefund'); }); \ No newline at end of file