Browse Source
			
			
			Merge branch 'order'
			
				
		Merge branch 'order'
	
		
	
			
				# Conflicts: # app/Commons/Log.php # app/Constants/ErrorCode.php # app/Constants/LogLabel.php # app/Controller/AbstractController.php # app/Controller/TestController.php # app/Model/OrderMain.php # app/Service/CouponService.php # app/Service/CouponServiceInterface.php # app/Service/UserService.php # app/Service/UserServiceInterface.php # composer.json # config/autoload/dependencies.php # config/autoload/exceptions.php # config/autoload/middlewares.php # config/routes.phpmaster
				 65 changed files with 4762 additions and 19 deletions
			
			
		- 
					73app/Amqp/Consumer/DevicOrderConsumer.php
 - 
					2app/Commons/Log.php
 - 
					16app/Constants/ErrorCode.php
 - 
					10app/Constants/LogLabel.php
 - 
					8app/Controller/AbstractController.php
 - 
					68app/Controller/AttachmentController.php
 - 
					9app/Controller/BaseController.php
 - 
					114app/Controller/DeviceController.php
 - 
					25app/Controller/IndexController.php
 - 
					380app/Controller/NotifyController.php
 - 
					38app/Controller/OrderController.php
 - 
					136app/Controller/PaymentController.php
 - 
					86app/Controller/StoreController.php
 - 
					35app/Controller/TestController.php
 - 
					35app/Exception/Handler/FilesystemExceptionHandler.php
 - 
					2app/Exception/Handler/ValidationExceptionHandler.php
 - 
					307app/Libs/FeiePrintClient.php
 - 
					1098app/Libs/MQTTClient.php
 - 
					3app/Model/Coupon.php
 - 
					10app/Model/CouponUserRec.php
 - 
					10app/Model/CouponUserUse.php
 - 
					14app/Model/Goods.php
 - 
					12app/Model/Order.php
 - 
					9app/Model/OrderGoods.php
 - 
					77app/Model/OrderMain.php
 - 
					31app/Model/OrderSalesStatistic.php
 - 
					16app/Model/SpeakerDevic.php
 - 
					18app/Model/SpecCombination.php
 - 
					9app/Model/Store.php
 - 
					9app/Model/StoreAccount.php
 - 
					11app/Model/SystemConfig.php
 - 
					1app/Model/Users.php
 - 
					47app/Request/AttachmentRequest.php
 - 
					26app/Request/BaseFormRequest.php
 - 
					46app/Request/ImageBase64Request.php
 - 
					46app/Request/ImageRequest.php
 - 
					42app/Request/OrderOfflineRequest.php
 - 
					70app/Request/OrderOnlineRequest.php
 - 
					38app/Request/WxminiPayRequest.php
 - 
					73app/Service/AttachmentService.php
 - 
					23app/Service/AttachmentServiceInterface.php
 - 
					63app/Service/CouponService.php
 - 
					14app/Service/CouponServiceInterface.php
 - 
					136app/Service/DeviceServiceImp.php
 - 
					12app/Service/DeviceServiceInterface.php
 - 
					232app/Service/FeiePrintService.php
 - 
					10app/Service/FeiePrintServiceInterface.php
 - 
					54app/Service/IOTAliService.php
 - 
					8app/Service/IOTServiceInterface.php
 - 
					209app/Service/MiniprogramService.php
 - 
					41app/Service/MiniprogramServiceInterface.php
 - 
					29app/Service/MqttServiceInterface.php
 - 
					81app/Service/MqttSpeakerService.php
 - 
					520app/Service/OrderService.php
 - 
					29app/Service/OrderServiceInterface.php
 - 
					24app/Service/UserService.php
 - 
					13app/Service/UserServiceInterface.php
 - 
					62app/TaskWorker/AliIotTask.php
 - 
					5composer.json
 - 
					7config/autoload/dependencies.php
 - 
					1config/autoload/exceptions.php
 - 
					94config/autoload/file.php
 - 
					24config/autoload/snowflake.php
 - 
					13config/config.php
 - 
					17config/routes.php
 
@ -0,0 +1,73 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Amqp\Consumer; | 
				
			|||
 | 
				
			|||
use App\Model\Order; | 
				
			|||
use App\Model\SpeakerDevic; | 
				
			|||
use App\Service\DeviceServiceInterface; | 
				
			|||
use Hyperf\Amqp\Result; | 
				
			|||
use Hyperf\Amqp\Annotation\Consumer; | 
				
			|||
use Hyperf\Amqp\Message\ConsumerMessage; | 
				
			|||
use Hyperf\DbConnection\Db; | 
				
			|||
use PhpAmqpLib\Message\AMQPMessage; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * @Consumer(exchange="devicOrder", routingKey="devicOrder", queue="devicOrder", nums=4) | 
				
			|||
 */ | 
				
			|||
class DevicOrderConsumer extends ConsumerMessage | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var DeviceServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $deviceService; | 
				
			|||
 | 
				
			|||
    public function consumeMessage($data, AMQPMessage $message): string | 
				
			|||
    { | 
				
			|||
        try { | 
				
			|||
 | 
				
			|||
            $orderMainId = $message->getBody(); | 
				
			|||
            $order = Order::query() | 
				
			|||
                ->select(['id', 'store_id', 'money']) | 
				
			|||
                ->where(['order_main_id' => $orderMainId, 'type' => 4, 'dm_state' => 2]) | 
				
			|||
                ->first(); | 
				
			|||
 | 
				
			|||
            if (is_null($order)||!$order) { | 
				
			|||
                return Result::ACK; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $deviceNames = SpeakerDevic::query() | 
				
			|||
                ->select(['device_name']) | 
				
			|||
                ->where(['store_id' => $order['store_id'], 'is_bind' => SpeakerDevic::IS_BIND_YES]) | 
				
			|||
                ->get() | 
				
			|||
                ->toArray(); | 
				
			|||
 | 
				
			|||
            if (empty($deviceNames)||!$deviceNames) { | 
				
			|||
                return Result::ACK; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $msg = "{\"msg\":\"到账".$order['money']."元\"}"; | 
				
			|||
            $res = $this->deviceService->pubMsgToStoreByDevName($deviceNames, $msg); | 
				
			|||
 | 
				
			|||
            if ($res == true) { | 
				
			|||
                return Result::ACK; | 
				
			|||
            } else { | 
				
			|||
                return Result::REQUEUE; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
        } catch (\Exception $e) { | 
				
			|||
            return Result::REQUEUE; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function isEnable(): bool | 
				
			|||
    { | 
				
			|||
        if(env('APP_ENV') == 'local') { | 
				
			|||
            return false; | 
				
			|||
        } | 
				
			|||
        return parent::isEnable(); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,68 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Controller; | 
				
			|||
 | 
				
			|||
use App\Request\AttachmentRequest; | 
				
			|||
use App\Request\ImageBase64Request; | 
				
			|||
use App\Service\AttachmentServiceInterface; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
use App\Request\ImageRequest; | 
				
			|||
use League\Flysystem\Filesystem; | 
				
			|||
 | 
				
			|||
class AttachmentController extends BaseController | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var AttachmentServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $attachmentService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 单文件表单上传 | 
				
			|||
     * @param AttachmentRequest $request | 
				
			|||
     * @param Filesystem $filesystem | 
				
			|||
     * @return \Psr\Http\Message\ResponseInterface | 
				
			|||
     */ | 
				
			|||
    public function upload(AttachmentRequest $request, Filesystem $filesystem) | 
				
			|||
    { | 
				
			|||
        $file = $this->request->file('upload'); | 
				
			|||
        $type = $this->request->input('type', ''); | 
				
			|||
 | 
				
			|||
        $fileName = $this->attachmentService->formUpload($file, $type, $filesystem, 'file'); | 
				
			|||
 | 
				
			|||
        return $this->success(['file_path' => $fileName]); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 单图表单上传 | 
				
			|||
     * @param ImageRequest $request | 
				
			|||
     * @param Filesystem $filesystem | 
				
			|||
     * @return \Psr\Http\Message\ResponseInterface | 
				
			|||
     */ | 
				
			|||
    public function uploadImage(ImageRequest $request, Filesystem $filesystem) | 
				
			|||
    { | 
				
			|||
        $file = $this->request->file('upload'); | 
				
			|||
        $type = $this->request->input('type', ''); | 
				
			|||
 | 
				
			|||
        $fileName = $this->attachmentService->formUpload($file, $type, $filesystem); | 
				
			|||
 | 
				
			|||
        return $this->success(['file_path' => $fileName]); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 单图base64上传 | 
				
			|||
     * @param ImageBase64Request $request | 
				
			|||
     * @param Filesystem $filesystem | 
				
			|||
     * @return \Psr\Http\Message\ResponseInterface | 
				
			|||
     */ | 
				
			|||
    public function uploadImageByBase64(ImageBase64Request $request, Filesystem $filesystem) | 
				
			|||
    { | 
				
			|||
        $base64Code = $this->request->input('upload'); | 
				
			|||
        $type = $this->request->input('type', ''); | 
				
			|||
 | 
				
			|||
        $fileName = $this->attachmentService->base64Upload($base64Code, $type, $filesystem); | 
				
			|||
 | 
				
			|||
        return $this->success(['file_path' => $fileName]); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,114 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Controller; | 
				
			|||
 | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
use App\Exception\BusinessException; | 
				
			|||
use App\Service\DeviceServiceInterface; | 
				
			|||
use Hyperf\Validation\ValidationException; | 
				
			|||
 | 
				
			|||
class DeviceController extends BaseController | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var DeviceServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $deviceService; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    public function bind() | 
				
			|||
    { | 
				
			|||
        $validator = $this->validationFactory->make( | 
				
			|||
            $this->request->all(), | 
				
			|||
            [ | 
				
			|||
                'store_id' => 'required|nonempty|integer', | 
				
			|||
                'device_name' => 'required|nonempty|alpha_num', | 
				
			|||
            ], | 
				
			|||
            [ | 
				
			|||
                'store_id.required' => '参数不正确', | 
				
			|||
                'store_id.nonempty' => '参数不正确', | 
				
			|||
                'store_id.integer' => '参数不正确', | 
				
			|||
                'device_name.required' => '参数不正确', | 
				
			|||
                'device_name.nonempty' => '参数不正确', | 
				
			|||
                'device_name.alpha_num' => '参数不正确', | 
				
			|||
            ] | 
				
			|||
        ); | 
				
			|||
 | 
				
			|||
        if ($validator->fails()) { | 
				
			|||
            // Handle exception
 | 
				
			|||
            throw new ValidationException($validator); | 
				
			|||
            return; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $store_id = $this->request->input('store_id'); | 
				
			|||
        $device_name = $this->request->input('device_name'); | 
				
			|||
 | 
				
			|||
        $sd = $this->deviceService->bindByStoreId($device_name, $store_id); | 
				
			|||
 | 
				
			|||
        if (is_null($sd)) { | 
				
			|||
            return $this->result(100, '', '绑定失败: 设备号已经被绑定或不存在'); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this->success($sd, '绑定成功'); | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function list() | 
				
			|||
    { | 
				
			|||
        $validator = $this->validationFactory->make( | 
				
			|||
            $this->request->all(), | 
				
			|||
            [ | 
				
			|||
                'store_id' => 'required|nonempty|integer', | 
				
			|||
            ], | 
				
			|||
            [ | 
				
			|||
                'store_id.required' => '参数不正确', | 
				
			|||
                'store_id.nonempty' => '参数不正确', | 
				
			|||
                'store_id.integer' => '参数不正确', | 
				
			|||
            ] | 
				
			|||
        ); | 
				
			|||
 | 
				
			|||
        if ($validator->fails()) { | 
				
			|||
            // Handle exception
 | 
				
			|||
            throw new ValidationException($validator); | 
				
			|||
            return; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $store_id = $this->request->input('store_id'); | 
				
			|||
 | 
				
			|||
        $devices = $this->deviceService->getListByStoreId($store_id); | 
				
			|||
 | 
				
			|||
        return $this->success($devices); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function unbind() | 
				
			|||
    { | 
				
			|||
        $validator = $this->validationFactory->make( | 
				
			|||
            $this->request->all(), | 
				
			|||
            [ | 
				
			|||
                'bind_id' => 'required|nonempty|integer', | 
				
			|||
            ], | 
				
			|||
            [ | 
				
			|||
                'bind_id.required' => '参数不正确', | 
				
			|||
                'bind_id.nonempty' => '参数不正确', | 
				
			|||
                'bind_id.integer' => '参数不正确', | 
				
			|||
            ] | 
				
			|||
        ); | 
				
			|||
 | 
				
			|||
        if ($validator->fails()) { | 
				
			|||
            // Handle exception
 | 
				
			|||
            throw new ValidationException($validator); | 
				
			|||
            return; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $bind_id = $this->request->input('bind_id'); | 
				
			|||
 | 
				
			|||
        $unbind_num = $this->deviceService->unbindById($bind_id); | 
				
			|||
 | 
				
			|||
        if ($unbind_num == 0) { | 
				
			|||
            return $this->result(100, '', '解绑失败: 设备已经解绑或不存在'); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this->success(['unbind' => $unbind_num]); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,380 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Controller; | 
				
			|||
 | 
				
			|||
use App\Constants\LogLabel; | 
				
			|||
use App\Model\Goods; | 
				
			|||
use App\Model\Order; | 
				
			|||
use App\Model\OrderGoods; | 
				
			|||
use App\Model\OrderMain; | 
				
			|||
use App\Model\OrderSalesStatistic; | 
				
			|||
use App\Model\SpecCombination; | 
				
			|||
use App\Model\Store; | 
				
			|||
use App\Model\StoreAccount; | 
				
			|||
use App\Model\SystemConfig; | 
				
			|||
use App\Model\Users; | 
				
			|||
use App\Service\DeviceServiceInterface; | 
				
			|||
use App\Service\FeiePrintServiceInterface; | 
				
			|||
use App\Service\MiniprogramServiceInterface; | 
				
			|||
use App\Service\MqttServiceInterface; | 
				
			|||
use App\Service\UserServiceInterface; | 
				
			|||
use EasyWeChat\Factory; | 
				
			|||
use Hyperf\DbConnection\Db; | 
				
			|||
use Hyperf\Guzzle\CoroutineHandler; | 
				
			|||
use Exception; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
use Hyperf\HttpMessage\Stream\SwooleStream; | 
				
			|||
use Symfony\Component\HttpFoundation\Request; | 
				
			|||
 | 
				
			|||
class NotifyController extends BaseController | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    const AWARD_LIMIT_AMOUNT = 3; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var MqttServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $mqttSpeakerService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var DeviceServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $deviceService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var MiniprogramServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $miniprogramService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var FeiePrintServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $feiePrintService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var UserServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $userService; | 
				
			|||
 | 
				
			|||
    public function wxminiOnline() | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        $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->handlePaidNotify(function ($message, $fail) use ($app) { | 
				
			|||
 | 
				
			|||
            Db::beginTransaction(); | 
				
			|||
            try { | 
				
			|||
                // 支付失败或者通知失败
 | 
				
			|||
                if ( | 
				
			|||
                    empty($message) | 
				
			|||
                    || $message['return_code'] != 'SUCCESS' | 
				
			|||
                    || !isset($message['result_code']) | 
				
			|||
                    || $message['result_code'] != 'SUCCESS' | 
				
			|||
                ) { | 
				
			|||
                    $this->log->event( | 
				
			|||
                        LogLabel::PAY_NOTIFY_WXMINI, | 
				
			|||
                        $message | 
				
			|||
                    ); | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    $fail('Unknown error but FAIL'); | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                // 查询订单
 | 
				
			|||
                $orderMain = OrderMain::query() | 
				
			|||
                    ->where([ | 
				
			|||
                        'global_order_id' => $message['out_trade_no'], | 
				
			|||
                        'type' => OrderMain::ORDER_TYPE_ONLINE | 
				
			|||
                    ]) | 
				
			|||
                    ->first(); | 
				
			|||
 | 
				
			|||
                // 订单不存在
 | 
				
			|||
                if (empty($orderMain)) { | 
				
			|||
                    $this->log->event( | 
				
			|||
                        LogLabel::PAY_NOTIFY_WXMINI, | 
				
			|||
                        ['global_order_id_fail' => $message['out_trade_no']] | 
				
			|||
                    ); | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    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); | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                // 喇叭通知,兼容旧音响,MQTT+IOT
 | 
				
			|||
                $res = $this->mqttSpeakerService->speakToStore($orderMain->id); | 
				
			|||
                $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id); | 
				
			|||
 | 
				
			|||
                // 公众号模板消息
 | 
				
			|||
                $res = $this->miniprogramService->sendTemMsgForOnlineOrder($orderMain->id); | 
				
			|||
 | 
				
			|||
                // 打印订单,自动打印 TODO 后续优化调用逻辑
 | 
				
			|||
                $res = $this->feiePrintService->feiePrint($orderMain->global_order_id); | 
				
			|||
 | 
				
			|||
                Db::commit(); | 
				
			|||
                return true; | 
				
			|||
 | 
				
			|||
            } catch (Exception $e) { | 
				
			|||
 | 
				
			|||
                $this->log->event( | 
				
			|||
                    LogLabel::PAY_NOTIFY_WXMINI, | 
				
			|||
                    ['exception_fail' => $e->getMessage()] | 
				
			|||
                ); | 
				
			|||
                Db::rollBack(); | 
				
			|||
                $fail('Exception'); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
        }); | 
				
			|||
 | 
				
			|||
        return $this->response | 
				
			|||
            ->withHeader('Content-Type', 'text/xml') | 
				
			|||
            ->withStatus(200) | 
				
			|||
            ->withBody(new SwooleStream($response->getContent())); | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function wxminiOffline() | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        $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->handlePaidNotify(function ($message, $fail) use ($app) { | 
				
			|||
 | 
				
			|||
            Db::beginTransaction(); | 
				
			|||
            try { | 
				
			|||
                // 支付失败或者通知失败
 | 
				
			|||
                if ( | 
				
			|||
                    empty($message) | 
				
			|||
                    || $message['return_code'] != 'SUCCESS' | 
				
			|||
                    || !isset($message['result_code']) | 
				
			|||
                    || $message['result_code'] != 'SUCCESS' | 
				
			|||
                ) { | 
				
			|||
                    $this->log->event( | 
				
			|||
                        LogLabel::PAY_NOTIFY_WXMINI, | 
				
			|||
                        $message | 
				
			|||
                    ); | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    $fail('Unknown error but FAIL'); | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                // 查询订单
 | 
				
			|||
                $orderMain = OrderMain::query() | 
				
			|||
                    ->where([ | 
				
			|||
                        'global_order_id' => $message['out_trade_no'], | 
				
			|||
                        'type' => OrderMain::ORDER_TYPE_OFFLINE | 
				
			|||
                    ]) | 
				
			|||
                    ->first(); | 
				
			|||
 | 
				
			|||
                // 订单不存在
 | 
				
			|||
                if (empty($orderMain)) { | 
				
			|||
                    $this->log->event( | 
				
			|||
                        LogLabel::PAY_NOTIFY_WXMINI, | 
				
			|||
                        ['global_order_id_fail' => $message['out_trade_no']] | 
				
			|||
                    ); | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    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']); | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                // 喇叭通知,兼容旧音响,MQTT+IOT
 | 
				
			|||
                $res = $this->mqttSpeakerService->speakToStore($orderMain->id); | 
				
			|||
                $res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id); | 
				
			|||
 | 
				
			|||
                // 公众号模板消息
 | 
				
			|||
                $res = $this->miniprogramService->sendTemMsgForOfflineOrder($orderMain->id); | 
				
			|||
 | 
				
			|||
                Db::commit(); | 
				
			|||
                return true; | 
				
			|||
 | 
				
			|||
            } catch (Exception $e) { | 
				
			|||
 | 
				
			|||
                $this->log->event( | 
				
			|||
                    LogLabel::PAY_NOTIFY_WXMINI, | 
				
			|||
                    ['exception_fail' => $e->getMessage()] | 
				
			|||
                ); | 
				
			|||
                Db::rollBack(); | 
				
			|||
                $fail('Exception'); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
        }); | 
				
			|||
 | 
				
			|||
        return $this->response | 
				
			|||
            ->withHeader('Content-Type', 'text/xml') | 
				
			|||
            ->withStatus(200) | 
				
			|||
            ->withBody(new SwooleStream($response->getContent())); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,38 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Controller; | 
				
			|||
 | 
				
			|||
use App\Constants\ErrorCode; | 
				
			|||
use App\Request\OrderOfflineRequest; | 
				
			|||
use App\Request\OrderOnlineRequest; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
use App\Service\OrderServiceInterface; | 
				
			|||
use Hyperf\HttpMessage\Stream\SwooleStream; | 
				
			|||
 | 
				
			|||
class OrderController extends BaseController | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var OrderServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $orderService; | 
				
			|||
 | 
				
			|||
    public function addOnlineOrder(OrderOnlineRequest $request) | 
				
			|||
    { | 
				
			|||
        $orderMainId = $this->orderService->addOnlineOrder($request->validated()); | 
				
			|||
        if (!is_int($orderMainId)) { | 
				
			|||
            return $this->result(ErrorCode::ORDER_FAILURE, '', $orderMainId); | 
				
			|||
        } | 
				
			|||
        return $this->success(['order_id' => $orderMainId]); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function addOfflineOrder(OrderOfflineRequest $request) | 
				
			|||
    { | 
				
			|||
        $orderMainId = $this->orderService->addOfflineOrder($request->validated()); | 
				
			|||
        if (!is_int($orderMainId)) { | 
				
			|||
            return $this->result(ErrorCode::ORDER_FAILURE, '', $orderMainId); | 
				
			|||
        } | 
				
			|||
        return $this->success(['order_id' => $orderMainId]); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,136 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Controller; | 
				
			|||
 | 
				
			|||
use App\Constants\ErrorCode; | 
				
			|||
use App\Model\OrderMain; | 
				
			|||
use App\Request\WxminiPayRequest; | 
				
			|||
 | 
				
			|||
use EasyWeChat\Factory; | 
				
			|||
use Hyperf\Guzzle\CoroutineHandler; | 
				
			|||
 | 
				
			|||
class PaymentController extends BaseController | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    public function wxminiPayOnline(WxminiPayRequest $request){ | 
				
			|||
 | 
				
			|||
        $data = $request->validated(); | 
				
			|||
 | 
				
			|||
        $config = config('wxpay'); | 
				
			|||
        $app = Factory::payment($config); | 
				
			|||
        $app['guzzle_handler'] = CoroutineHandler::class; | 
				
			|||
 | 
				
			|||
        // 待支付的,未超时(15min,900sec)的订单
 | 
				
			|||
        $orderMain = OrderMain::query() | 
				
			|||
            ->where(['state' => OrderMain::ORDER_STATE_UNPAY, 'id' => $data['order_id']]) | 
				
			|||
            ->where('time', '>=', date('Y-m-d H:i:s', (time()-900))) | 
				
			|||
            ->first(); | 
				
			|||
 | 
				
			|||
        if (empty($orderMain)) { | 
				
			|||
            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' => 1, | 
				
			|||
            'notify_url' => config('site_host') . '/wechat/notify/wxminionline', | 
				
			|||
            'trade_type' => 'JSAPI', | 
				
			|||
            'openid' => $data['openid'], | 
				
			|||
        ]); | 
				
			|||
 | 
				
			|||
        // 返回支付参数给前端
 | 
				
			|||
        $parameters = [ | 
				
			|||
            'appId' => $result['appid'], | 
				
			|||
            'timeStamp' => '' . time() . '', | 
				
			|||
            'nonceStr' => uniqid(), | 
				
			|||
            'package' => 'prepay_id=' . $result['prepay_id'], | 
				
			|||
            'signType' => 'MD5' | 
				
			|||
        ]; | 
				
			|||
 | 
				
			|||
        $parameters['paySign'] = $this->signture($parameters, $config['key']); | 
				
			|||
 | 
				
			|||
        return $this->success($parameters); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function wxminiPayOffline(WxminiPayRequest $request){ | 
				
			|||
 | 
				
			|||
        $data = $request->validated(); | 
				
			|||
 | 
				
			|||
        $config = config('wxpay'); | 
				
			|||
        $app = Factory::payment($config); | 
				
			|||
        $app['guzzle_handler'] = CoroutineHandler::class; | 
				
			|||
 | 
				
			|||
        // 待支付的,未超时(15min,900sec)的订单
 | 
				
			|||
        $orderMain = OrderMain::query() | 
				
			|||
            ->where(['dm_state' => OrderMain::ORDER_STATE_UNPAY, 'id' => $data['order_id']]) | 
				
			|||
            ->first(); | 
				
			|||
 | 
				
			|||
        if (empty($orderMain)) { | 
				
			|||
            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), | 
				
			|||
            'notify_url' => config('site_host') . '/wechat/notify/wxminioffline', | 
				
			|||
            'trade_type' => 'JSAPI', | 
				
			|||
            'openid' => $data['openid'], | 
				
			|||
        ]); | 
				
			|||
 | 
				
			|||
        // 返回支付参数给前端
 | 
				
			|||
        $parameters = [ | 
				
			|||
            'appId' => $result['appid'], | 
				
			|||
            'timeStamp' => '' . time() . '', | 
				
			|||
            'nonceStr' => uniqid(), | 
				
			|||
            'package' => 'prepay_id=' . $result['prepay_id'], | 
				
			|||
            'signType' => 'MD5' | 
				
			|||
        ]; | 
				
			|||
 | 
				
			|||
        $parameters['paySign'] = $this->signture($parameters, $config['key']); | 
				
			|||
 | 
				
			|||
        return $this->success($parameters); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 支付参数加签 | 
				
			|||
     * @param $parameters | 
				
			|||
     * @param $key | 
				
			|||
     * @return string | 
				
			|||
     */ | 
				
			|||
    private function signture($parameters, $key) | 
				
			|||
    { | 
				
			|||
        // 按字典序排序参数
 | 
				
			|||
        ksort($parameters); | 
				
			|||
 | 
				
			|||
        // http_query
 | 
				
			|||
        $queryParams = $this->http_query($parameters); | 
				
			|||
 | 
				
			|||
        // 加入KEY
 | 
				
			|||
        $queryParams = $queryParams . "&key=" . $key; | 
				
			|||
 | 
				
			|||
        // MD5加密
 | 
				
			|||
        $queryParams = md5($queryParams); | 
				
			|||
 | 
				
			|||
        // 字符转为大写
 | 
				
			|||
        return strtoupper($queryParams); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 参数转为http query字串 | 
				
			|||
     * @param $parameters | 
				
			|||
     * @return string | 
				
			|||
     */ | 
				
			|||
    private function http_query($parameters) { | 
				
			|||
 | 
				
			|||
        $http_query = []; | 
				
			|||
        foreach ($parameters as $key => $value) { | 
				
			|||
            $http_query[] = $key.'='.$value; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return implode('&', $http_query); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,86 @@ | 
				
			|||
<?php | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Controller; | 
				
			|||
 | 
				
			|||
use Hyperf\DbConnection\Db; | 
				
			|||
use Hyperf\HttpServer\Annotation\AutoController; | 
				
			|||
use OSS\Core\OssException; | 
				
			|||
use OSS\OssClient; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * @AutoController() | 
				
			|||
 * Class StoreController | 
				
			|||
 * @package App\Controller | 
				
			|||
 */ | 
				
			|||
class StoreController extends BaseController | 
				
			|||
{ | 
				
			|||
    public function infoEdit() | 
				
			|||
    { | 
				
			|||
        $id = $this->request->input('id'); | 
				
			|||
        if (empty($id)) { | 
				
			|||
            return $this->result(1, [], 'id不能为空'); | 
				
			|||
        } | 
				
			|||
        if ($this->request->isMethod('post')) { | 
				
			|||
            $logo         = $this->request->input('logo'); | 
				
			|||
            $name         = $this->request->input('name'); | 
				
			|||
            $tel          = $this->request->input('tel'); | 
				
			|||
            $address      = $this->request->input('address'); | 
				
			|||
            $coordinates  = $this->request->input('coordinates'); | 
				
			|||
            $capita       = $this->request->input('capita'); | 
				
			|||
            $start_at     = $this->request->input('start_at'); | 
				
			|||
            $announcement = $this->request->input('announcement'); | 
				
			|||
            $environment  = $this->request->input('environment'); | 
				
			|||
 | 
				
			|||
            //>>1上传logo到阿里云oss
 | 
				
			|||
            //>>2.上传商家环境到阿里云oss
 | 
				
			|||
            //>>3.保存数据到数据库存
 | 
				
			|||
            $fileNameLogo = $object = 'public/upload/' . date('Y') . '/' . date('m-d') . '/' . rand(0, 9999999999999999) . '.jpg'; | 
				
			|||
            $fileUpload   = new FileUpload(); | 
				
			|||
            $resLogo      = $fileUpload->ossUpload($logo, $fileNameLogo); | 
				
			|||
            if (isset($resLogo['info']['http_code']) && $resLogo['info']['http_code'] == 200) { | 
				
			|||
                $logo_url = $fileNameLogo; | 
				
			|||
            } else { | 
				
			|||
                return $this->result(1, []); | 
				
			|||
            } | 
				
			|||
            $environments = explode(',', $environment); | 
				
			|||
            $envPaths     = []; | 
				
			|||
            foreach ($environments as $env) { | 
				
			|||
                $fileNameEnv = $object = 'public/upload/' . date('Y') . '/' . date('m-d') . '/' . rand(0, 9999999999999999) . '.jpg'; | 
				
			|||
                $resEnv      = $fileUpload->ossUpload($env, $fileNameEnv); | 
				
			|||
                if (isset($resEnv['info']['http_code']) && $resLogo['info']['http_code'] == 200) { | 
				
			|||
                    $envPaths[] = $fileNameEnv; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
            if (count($envPaths)) { | 
				
			|||
                $envPath = implode(',', $envPaths); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $res = Db::table('ims_cjdc_store')->where('id', $id)->update([ | 
				
			|||
                'logo'         => $logo_url ?? "", | 
				
			|||
                'name'         => $name, | 
				
			|||
                'tel'          => $tel, | 
				
			|||
                'address'      => $address, | 
				
			|||
                'coordinates'  => $coordinates, | 
				
			|||
                'capita'       => $capita, | 
				
			|||
                'start_at'     => $start_at, | 
				
			|||
                'announcement' => $announcement, | 
				
			|||
                'environment'  => $envPath ?? "", | 
				
			|||
            ]); | 
				
			|||
            return $this->success($res); | 
				
			|||
        } | 
				
			|||
//'id','name','logo','tel','address','coordinates','capita','start_at','announcement','environment'
 | 
				
			|||
        //获取店铺信息
 | 
				
			|||
        $data = Db::table('ims_cjdc_store') | 
				
			|||
            ->select(['id','name','logo','tel','address','coordinates','capita','start_at','announcement','environment']) | 
				
			|||
            ->where('id',$id) | 
				
			|||
            ->first(); | 
				
			|||
        if ($data){ | 
				
			|||
            $data->site = config('site_host'); | 
				
			|||
        } | 
				
			|||
        return $this->success($data); | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,35 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Exception\Handler; | 
				
			|||
 | 
				
			|||
use App\Constants\ErrorCode; | 
				
			|||
use Hyperf\ExceptionHandler\ExceptionHandler; | 
				
			|||
use Hyperf\HttpMessage\Stream\SwooleStream; | 
				
			|||
use League\Flysystem\FilesystemException; | 
				
			|||
use Psr\Http\Message\ResponseInterface; | 
				
			|||
use Throwable; | 
				
			|||
 | 
				
			|||
class FilesystemExceptionHandler extends ExceptionHandler | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    public function handle(Throwable $throwable, ResponseInterface $response) | 
				
			|||
    { | 
				
			|||
        $this->stopPropagation(); | 
				
			|||
 | 
				
			|||
        $content = json_encode([ | 
				
			|||
            "status" => 'error', | 
				
			|||
            "code" => ErrorCode::UPLOAD_INVALID, | 
				
			|||
            "result" => [], | 
				
			|||
            "message" => $throwable->getMessage() | 
				
			|||
        ]); | 
				
			|||
 | 
				
			|||
        return $response->withHeader('Content-Type', 'application/json') | 
				
			|||
            ->withStatus($throwable->status) | 
				
			|||
            ->withBody(new SwooleStream($content)); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function isValid(Throwable $throwable): bool | 
				
			|||
    { | 
				
			|||
        return $throwable instanceof FilesystemException; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,307 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Libs; | 
				
			|||
 | 
				
			|||
class FeiePrintClient { | 
				
			|||
    // Request vars
 | 
				
			|||
    var $host; | 
				
			|||
    var $port; | 
				
			|||
    var $path; | 
				
			|||
    var $method; | 
				
			|||
    var $postdata = ''; | 
				
			|||
    var $cookies = array(); | 
				
			|||
    var $referer; | 
				
			|||
    var $accept = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,image/jpeg,image/gif,*/*'; | 
				
			|||
    var $accept_encoding = 'gzip'; | 
				
			|||
    var $accept_language = 'en-us'; | 
				
			|||
    var $user_agent = 'Incutio HttpClient v0.9'; | 
				
			|||
    var $timeout = 20; | 
				
			|||
    var $use_gzip = true; | 
				
			|||
    var $persist_cookies = true; | 
				
			|||
    var $persist_referers = true; | 
				
			|||
    var $debug = false; | 
				
			|||
    var $handle_redirects = true; | 
				
			|||
    var $max_redirects = 5; | 
				
			|||
    var $headers_only = false; | 
				
			|||
    var $username; | 
				
			|||
    var $password; | 
				
			|||
    var $status; | 
				
			|||
    var $headers = array(); | 
				
			|||
    var $content = ''; | 
				
			|||
    var $errormsg; | 
				
			|||
    var $redirect_count = 0; | 
				
			|||
    var $cookie_host = ''; | 
				
			|||
    function __construct($host, $port=80) { | 
				
			|||
        $this->host = $host; | 
				
			|||
        $this->port = $port; | 
				
			|||
    } | 
				
			|||
    function get($path, $data = false) { | 
				
			|||
        $this->path = $path; | 
				
			|||
        $this->method = 'GET'; | 
				
			|||
        if ($data) { | 
				
			|||
            $this->path .= '?'.$this->buildQueryString($data); | 
				
			|||
        } | 
				
			|||
        return $this->doRequest(); | 
				
			|||
    } | 
				
			|||
    function post($path, $data) { | 
				
			|||
        $this->path = $path; | 
				
			|||
        $this->method = 'POST'; | 
				
			|||
        $this->postdata = $this->buildQueryString($data); | 
				
			|||
        return $this->doRequest(); | 
				
			|||
    } | 
				
			|||
    function buildQueryString($data) { | 
				
			|||
        $querystring = ''; | 
				
			|||
        if (is_array($data)) { | 
				
			|||
            foreach ($data as $key => $val) { | 
				
			|||
                if (is_array($val)) { | 
				
			|||
                    foreach ($val as $val2) { | 
				
			|||
                        $querystring .= urlencode($key).'='.urlencode($val2).'&'; | 
				
			|||
                    } | 
				
			|||
                } else { | 
				
			|||
                    $querystring .= urlencode($key).'='.urlencode($val).'&'; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
            $querystring = substr($querystring, 0, -1); // Eliminate unnecessary &
 | 
				
			|||
        } else { | 
				
			|||
            $querystring = $data; | 
				
			|||
        } | 
				
			|||
        return $querystring; | 
				
			|||
    } | 
				
			|||
    function doRequest() { | 
				
			|||
        if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) { | 
				
			|||
            switch($errno) { | 
				
			|||
                case -3: | 
				
			|||
                    $this->errormsg = 'Socket creation failed (-3)'; | 
				
			|||
                case -4: | 
				
			|||
                    $this->errormsg = 'DNS lookup failure (-4)'; | 
				
			|||
                case -5: | 
				
			|||
                    $this->errormsg = 'Connection refused or timed out (-5)'; | 
				
			|||
                default: | 
				
			|||
                    $this->errormsg = 'Connection failed ('.$errno.')'; | 
				
			|||
                    $this->errormsg .= ' '.$errstr; | 
				
			|||
                    $this->debug($this->errormsg); | 
				
			|||
            } | 
				
			|||
            return false; | 
				
			|||
        } | 
				
			|||
        socket_set_timeout($fp, $this->timeout); | 
				
			|||
        $request = $this->buildRequest(); | 
				
			|||
        $this->debug('Request', $request); | 
				
			|||
        fwrite($fp, $request); | 
				
			|||
        $this->headers = array(); | 
				
			|||
        $this->content = ''; | 
				
			|||
        $this->errormsg = ''; | 
				
			|||
        $inHeaders = true; | 
				
			|||
        $atStart = true; | 
				
			|||
        while (!feof($fp)) { | 
				
			|||
            $line = fgets($fp, 4096); | 
				
			|||
            if ($atStart) { | 
				
			|||
                $atStart = false; | 
				
			|||
                if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) { | 
				
			|||
                    $this->errormsg = "Status code line invalid: ".htmlentities($line); | 
				
			|||
                    $this->debug($this->errormsg); | 
				
			|||
                    return false; | 
				
			|||
                } | 
				
			|||
                $http_version = $m[1]; | 
				
			|||
                $this->status = $m[2]; | 
				
			|||
                $status_string = $m[3]; | 
				
			|||
                $this->debug(trim($line)); | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
            if ($inHeaders) { | 
				
			|||
                if (trim($line) == '') { | 
				
			|||
                    $inHeaders = false; | 
				
			|||
                    $this->debug('Received Headers', $this->headers); | 
				
			|||
                    if ($this->headers_only) { | 
				
			|||
                        break; | 
				
			|||
                    } | 
				
			|||
                    continue; | 
				
			|||
                } | 
				
			|||
                if (!preg_match('/([^:]+):\\s*(.*)/', $line, $m)) { | 
				
			|||
                    continue; | 
				
			|||
                } | 
				
			|||
                $key = strtolower(trim($m[1])); | 
				
			|||
                $val = trim($m[2]); | 
				
			|||
                if (isset($this->headers[$key])) { | 
				
			|||
                    if (is_array($this->headers[$key])) { | 
				
			|||
                        $this->headers[$key][] = $val; | 
				
			|||
                    } else { | 
				
			|||
                        $this->headers[$key] = array($this->headers[$key], $val); | 
				
			|||
                    } | 
				
			|||
                } else { | 
				
			|||
                    $this->headers[$key] = $val; | 
				
			|||
                } | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
            $this->content .= $line; | 
				
			|||
        } | 
				
			|||
        fclose($fp); | 
				
			|||
        if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] == 'gzip') { | 
				
			|||
            $this->debug('Content is gzip encoded, unzipping it'); | 
				
			|||
            $this->content = substr($this->content, 10); | 
				
			|||
            $this->content = gzinflate($this->content); | 
				
			|||
        } | 
				
			|||
        if ($this->persist_cookies && isset($this->headers['set-cookie']) && $this->host == $this->cookie_host) { | 
				
			|||
            $cookies = $this->headers['set-cookie']; | 
				
			|||
            if (!is_array($cookies)) { | 
				
			|||
                $cookies = array($cookies); | 
				
			|||
            } | 
				
			|||
            foreach ($cookies as $cookie) { | 
				
			|||
                if (preg_match('/([^=]+)=([^;]+);/', $cookie, $m)) { | 
				
			|||
                    $this->cookies[$m[1]] = $m[2]; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
            $this->cookie_host = $this->host; | 
				
			|||
        } | 
				
			|||
        if ($this->persist_referers) { | 
				
			|||
            $this->debug('Persisting referer: '.$this->getRequestURL()); | 
				
			|||
            $this->referer = $this->getRequestURL(); | 
				
			|||
        } | 
				
			|||
        if ($this->handle_redirects) { | 
				
			|||
            if (++$this->redirect_count >= $this->max_redirects) { | 
				
			|||
                $this->errormsg = 'Number of redirects exceeded maximum ('.$this->max_redirects.')'; | 
				
			|||
                $this->debug($this->errormsg); | 
				
			|||
                $this->redirect_count = 0; | 
				
			|||
                return false; | 
				
			|||
            } | 
				
			|||
            $location = isset($this->headers['location']) ? $this->headers['location'] : ''; | 
				
			|||
            $uri = isset($this->headers['uri']) ? $this->headers['uri'] : ''; | 
				
			|||
            if ($location || $uri) { | 
				
			|||
                $url = parse_url($location.$uri); | 
				
			|||
                return $this->get($url['path']); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
    function buildRequest() { | 
				
			|||
        $headers = array(); | 
				
			|||
        $headers[] = "{$this->method} {$this->path} HTTP/1.0"; | 
				
			|||
        $headers[] = "Host: {$this->host}"; | 
				
			|||
        $headers[] = "User-Agent: {$this->user_agent}"; | 
				
			|||
        $headers[] = "Accept: {$this->accept}"; | 
				
			|||
        if ($this->use_gzip) { | 
				
			|||
            $headers[] = "Accept-encoding: {$this->accept_encoding}"; | 
				
			|||
        } | 
				
			|||
        $headers[] = "Accept-language: {$this->accept_language}"; | 
				
			|||
        if ($this->referer) { | 
				
			|||
            $headers[] = "Referer: {$this->referer}"; | 
				
			|||
        } | 
				
			|||
        if ($this->cookies) { | 
				
			|||
            $cookie = 'Cookie: '; | 
				
			|||
            foreach ($this->cookies as $key => $value) { | 
				
			|||
                $cookie .= "$key=$value; "; | 
				
			|||
            } | 
				
			|||
            $headers[] = $cookie; | 
				
			|||
        } | 
				
			|||
        if ($this->username && $this->password) { | 
				
			|||
            $headers[] = 'Authorization: BASIC '.base64_encode($this->username.':'.$this->password); | 
				
			|||
        } | 
				
			|||
        if ($this->postdata) { | 
				
			|||
            $headers[] = 'Content-Type: application/x-www-form-urlencoded'; | 
				
			|||
            $headers[] = 'Content-Length: '.strlen($this->postdata); | 
				
			|||
        } | 
				
			|||
        $request = implode("\r\n", $headers)."\r\n\r\n".$this->postdata; | 
				
			|||
        return $request; | 
				
			|||
    } | 
				
			|||
    function getStatus() { | 
				
			|||
        return $this->status; | 
				
			|||
    } | 
				
			|||
    function getContent() { | 
				
			|||
        return $this->content; | 
				
			|||
    } | 
				
			|||
    function getHeaders() { | 
				
			|||
        return $this->headers; | 
				
			|||
    } | 
				
			|||
    function getHeader($header) { | 
				
			|||
        $header = strtolower($header); | 
				
			|||
        if (isset($this->headers[$header])) { | 
				
			|||
            return $this->headers[$header]; | 
				
			|||
        } else { | 
				
			|||
            return false; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
    function getError() { | 
				
			|||
        return $this->errormsg; | 
				
			|||
    } | 
				
			|||
    function getCookies() { | 
				
			|||
        return $this->cookies; | 
				
			|||
    } | 
				
			|||
    function getRequestURL() { | 
				
			|||
        $url = 'https://'.$this->host; | 
				
			|||
        if ($this->port != 80) { | 
				
			|||
            $url .= ':'.$this->port; | 
				
			|||
        } | 
				
			|||
        $url .= $this->path; | 
				
			|||
        return $url; | 
				
			|||
    } | 
				
			|||
    function setUserAgent($string) { | 
				
			|||
        $this->user_agent = $string; | 
				
			|||
    } | 
				
			|||
    function setAuthorization($username, $password) { | 
				
			|||
        $this->username = $username; | 
				
			|||
        $this->password = $password; | 
				
			|||
    } | 
				
			|||
    function setCookies($array) { | 
				
			|||
        $this->cookies = $array; | 
				
			|||
    } | 
				
			|||
    function useGzip($boolean) { | 
				
			|||
        $this->use_gzip = $boolean; | 
				
			|||
    } | 
				
			|||
    function setPersistCookies($boolean) { | 
				
			|||
        $this->persist_cookies = $boolean; | 
				
			|||
    } | 
				
			|||
    function setPersistReferers($boolean) { | 
				
			|||
        $this->persist_referers = $boolean; | 
				
			|||
    } | 
				
			|||
    function setHandleRedirects($boolean) { | 
				
			|||
        $this->handle_redirects = $boolean; | 
				
			|||
    } | 
				
			|||
    function setMaxRedirects($num) { | 
				
			|||
        $this->max_redirects = $num; | 
				
			|||
    } | 
				
			|||
    function setHeadersOnly($boolean) { | 
				
			|||
        $this->headers_only = $boolean; | 
				
			|||
    } | 
				
			|||
    function setDebug($boolean) { | 
				
			|||
        $this->debug = $boolean; | 
				
			|||
    } | 
				
			|||
    function quickGet($url) { | 
				
			|||
        $bits = parse_url($url); | 
				
			|||
        $host = $bits['host']; | 
				
			|||
        $port = isset($bits['port']) ? $bits['port'] : 80; | 
				
			|||
        $path = isset($bits['path']) ? $bits['path'] : '/'; | 
				
			|||
        if (isset($bits['query'])) { | 
				
			|||
            $path .= '?'.$bits['query']; | 
				
			|||
        } | 
				
			|||
        $client = new HttpClient($host, $port); | 
				
			|||
        if (!$client->get($path)) { | 
				
			|||
            return false; | 
				
			|||
        } else { | 
				
			|||
            return $client->getContent(); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
    function quickPost($url, $data) { | 
				
			|||
        $bits = parse_url($url); | 
				
			|||
        $host = $bits['host']; | 
				
			|||
        $port = isset($bits['port']) ? $bits['port'] : 80; | 
				
			|||
        $path = isset($bits['path']) ? $bits['path'] : '/'; | 
				
			|||
        $client = new HttpClient($host, $port); | 
				
			|||
        if (!$client->post($path, $data)) { | 
				
			|||
            return false; | 
				
			|||
        } else { | 
				
			|||
            return $client->getContent(); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
    function debug($msg, $object = false) { | 
				
			|||
        if ($this->debug) { | 
				
			|||
            print '<div style="border: 1px solid red; padding: 0.5em; margin: 0.5em;"><strong>HttpClient Debug:</strong> '.$msg; | 
				
			|||
            if ($object) { | 
				
			|||
                ob_start(); | 
				
			|||
                print_r($object); | 
				
			|||
                $content = htmlentities(ob_get_contents()); | 
				
			|||
                ob_end_clean(); | 
				
			|||
                print '<pre>'.$content.'</pre>'; | 
				
			|||
            } | 
				
			|||
            print '</div>'; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
						
							
						
						
							1098
	
						
						app/Libs/MQTTClient.php
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						@ -0,0 +1,10 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class CouponUserRec extends Model | 
				
			|||
{ | 
				
			|||
    protected $table = 'ims_system_coupon_user_receive'; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,10 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class CouponUserUse extends Model | 
				
			|||
{ | 
				
			|||
    protected $table = 'ims_system_coupon_user_use'; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,14 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class Goods extends Model | 
				
			|||
{ | 
				
			|||
    const INVENTORY_NOLIMIT = 1; | 
				
			|||
 | 
				
			|||
    protected $table = 'ims_cjdc_goods'; | 
				
			|||
    public $timestamps = false; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,12 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class Order extends Model | 
				
			|||
{ | 
				
			|||
    protected $table = 'ims_cjdc_order'; | 
				
			|||
    public $timestamps = false; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,9 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
class OrderGoods extends Model | 
				
			|||
{ | 
				
			|||
    protected $table = 'ims_cjdc_order_goods'; | 
				
			|||
    public $timestamps = false; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,31 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare (strict_types=1); | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
use Hyperf\DbConnection\Model\Model; | 
				
			|||
/** | 
				
			|||
 */ | 
				
			|||
class OrderSalesStatistic extends Model | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * The table associated with the model. | 
				
			|||
     * | 
				
			|||
     * @var string | 
				
			|||
     */ | 
				
			|||
    protected $table = 'ims_cjdc_order_sales_statistics'; | 
				
			|||
    /** | 
				
			|||
     * The attributes that are mass assignable. | 
				
			|||
     * | 
				
			|||
     * @var array | 
				
			|||
     */ | 
				
			|||
    protected $fillable = []; | 
				
			|||
    /** | 
				
			|||
     * The attributes that should be cast to native types. | 
				
			|||
     * | 
				
			|||
     * @var array | 
				
			|||
     */ | 
				
			|||
    protected $casts = []; | 
				
			|||
 | 
				
			|||
    public $timestamps = false; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,16 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
use App\Model\Model; | 
				
			|||
 | 
				
			|||
class SpeakerDevic extends Model | 
				
			|||
{ | 
				
			|||
    const IS_BIND_YES = 1; | 
				
			|||
    const IS_BIND_NO = 0; | 
				
			|||
 | 
				
			|||
    protected $table = 'lanzu_service_speakers'; | 
				
			|||
 | 
				
			|||
    protected $fillable = ['store_id', 'device_name', 'state', 'market_id', 'bind_time', 'is_bind']; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,18 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class SpecCombination extends Model | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    protected $table = 'ims_cjdc_spec_combination'; | 
				
			|||
    public $timestamps = false; | 
				
			|||
 | 
				
			|||
    public function goods() | 
				
			|||
    { | 
				
			|||
        return $this->belongsTo(Goods::class, 'good_id', 'id'); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,9 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
class Store extends Model | 
				
			|||
{ | 
				
			|||
    protected $table = 'ims_cjdc_store'; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,9 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
class StoreAccount extends Model | 
				
			|||
{ | 
				
			|||
    protected $table = 'ims_cjdc_store_account'; | 
				
			|||
    public $timestamps = false; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,11 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Model; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class SystemConfig extends Model | 
				
			|||
{ | 
				
			|||
    protected $table = 'ims_cjdc_system_config'; | 
				
			|||
    public $timestamps = false; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,47 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Request; | 
				
			|||
 | 
				
			|||
use Hyperf\Validation\Request\FormRequest; | 
				
			|||
 | 
				
			|||
class AttachmentRequest extends FormRequest | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Determine if the user is authorized to make this request. | 
				
			|||
     */ | 
				
			|||
    public function authorize(): bool | 
				
			|||
    { | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Get the validation rules that apply to the request. | 
				
			|||
     */ | 
				
			|||
    public function rules(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload' => 'required|nonempty|file|ext_not_in', | 
				
			|||
            'type' => 'nonempty|alpha' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function messages(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload.required' => '未选择上传的文件', | 
				
			|||
            'upload.nonempty' => '文件异常', | 
				
			|||
            'upload.file' => '文件上传不成功', | 
				
			|||
            'upload.ext_not_in' => '文件不允许上传', | 
				
			|||
            'type.nonempty' => '文件类型参数异常', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function attributes(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload' => '文件' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,26 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Request; | 
				
			|||
 | 
				
			|||
use Hyperf\Validation\Request\FormRequest; | 
				
			|||
use Psr\Http\Message\ResponseInterface; | 
				
			|||
 | 
				
			|||
class BaseFormRequest extends FormRequest | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    public function authorize(): bool | 
				
			|||
    { | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    //复写返回状态,200
 | 
				
			|||
    // public function response(): ResponseInterface
 | 
				
			|||
    // {
 | 
				
			|||
    //     /** @var ResponseInterface $response */
 | 
				
			|||
    //     $response = Context::get(ResponseInterface::class);
 | 
				
			|||
 | 
				
			|||
    //     return $response->withStatus(200);
 | 
				
			|||
    // }
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,46 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Request; | 
				
			|||
 | 
				
			|||
use Hyperf\Validation\Request\FormRequest; | 
				
			|||
 | 
				
			|||
class ImageBase64Request extends FormRequest | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Determine if the user is authorized to make this request. | 
				
			|||
     */ | 
				
			|||
    public function authorize(): bool | 
				
			|||
    { | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Get the validation rules that apply to the request. | 
				
			|||
     */ | 
				
			|||
    public function rules(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload' => 'required|nonempty|base64:image', | 
				
			|||
            'type' => 'nonempty|alpha' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function messages(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload.required' => '未选择上传的文件', | 
				
			|||
            'upload.base64' => '文件不是正常的图片', | 
				
			|||
            'upload.nonempty' => '文件异常', | 
				
			|||
            'type.nonempty' => '图片类型参数异常', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function attributes(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload' => '图片' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,46 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Request; | 
				
			|||
 | 
				
			|||
use Hyperf\Validation\Request\FormRequest; | 
				
			|||
 | 
				
			|||
class ImageRequest extends FormRequest | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Determine if the user is authorized to make this request. | 
				
			|||
     */ | 
				
			|||
    public function authorize(): bool | 
				
			|||
    { | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Get the validation rules that apply to the request. | 
				
			|||
     */ | 
				
			|||
    public function rules(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload' => 'required|nonempty|file|image', | 
				
			|||
            'type' => 'nonempty|alpha' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function messages(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload.required' => '未选择上传的文件', | 
				
			|||
            'upload.image' => '文件不是正常的图片', | 
				
			|||
            'upload.nonempty' => '文件异常', | 
				
			|||
            'type.nonempty' => '图片类型参数异常', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function attributes(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'upload' => '图片' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,42 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Request; | 
				
			|||
 | 
				
			|||
class OrderOfflineRequest extends BaseFormRequest | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Determine if the user is authorized to make this request. | 
				
			|||
     */ | 
				
			|||
    public function authorize(): bool | 
				
			|||
    { | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Get the validation rules that apply to the request. | 
				
			|||
     */ | 
				
			|||
    public function rules(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'store_id' => 'required|nonempty|integer', | 
				
			|||
            'user_id' => 'required|nonempty|integer', | 
				
			|||
            'money' => 'required|nonempty', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function messages(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            '*.*' => ':attribute 参数异常' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function attributes(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
 | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,70 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Request; | 
				
			|||
 | 
				
			|||
class OrderOnlineRequest extends BaseFormRequest | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Determine if the user is authorized to make this request. | 
				
			|||
     */ | 
				
			|||
    public function authorize(): bool | 
				
			|||
    { | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Get the validation rules that apply to the request. | 
				
			|||
     */ | 
				
			|||
    public function rules(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'order_num' => 'nonempty', | 
				
			|||
            'delivery_no' => '', | 
				
			|||
            'dada_fee' => 'nonempty', | 
				
			|||
            'market_id' => 'required|nonempty|integer', | 
				
			|||
            'user_id' => 'required|nonempty|integer', | 
				
			|||
            'money' => 'required|nonempty', | 
				
			|||
            'box_money' => '', | 
				
			|||
            'ps_money' => '', | 
				
			|||
            'mj_money' => '', | 
				
			|||
            'xyh_money' => '', | 
				
			|||
            'yhq_money' => '', | 
				
			|||
            'yhq_money2' => '', | 
				
			|||
            'zk_money' => '', | 
				
			|||
            'tel' => 'required|nonempty', | 
				
			|||
            'name' => 'required|nonempty', | 
				
			|||
            'address' => 'required|nonempty', | 
				
			|||
            'area' => '', | 
				
			|||
            'lat' => 'required|nonempty', | 
				
			|||
            'lng' => 'required|nonempty', | 
				
			|||
            'note' => '', | 
				
			|||
            'type' => 'required|nonempty', | 
				
			|||
            'form_id' => '', | 
				
			|||
            'form_id2' => '', | 
				
			|||
            'delivery_time' => '', | 
				
			|||
            'order_type' => 'nonempty', | 
				
			|||
            'pay_type' => 'nonempty', | 
				
			|||
            'coupon_id' => '', | 
				
			|||
            'coupon_id2' => '', | 
				
			|||
            'uniacid' => 'nonempty', | 
				
			|||
            'store_list' => 'nonempty', | 
				
			|||
            'receive_coupon_ids' => '', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function messages(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            '*.*' => ':attribute 参数异常' | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function attributes(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
 | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,38 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
 | 
				
			|||
namespace App\Request; | 
				
			|||
 | 
				
			|||
use App\Request\BaseFormRequest; | 
				
			|||
 | 
				
			|||
class WxminiPayRequest extends BaseFormRequest | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Get the validation rules that apply to the request. | 
				
			|||
     */ | 
				
			|||
    public function rules(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'order_id' => 'required|nonempty|integer', | 
				
			|||
            'openid' => 'required|nonempty', | 
				
			|||
            'money' => 'required|nonempty', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function messages(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            '*.*' => ':attribute 参数异常', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function attributes(): array | 
				
			|||
    { | 
				
			|||
        return [ | 
				
			|||
            'order_id' => '订单', | 
				
			|||
            'money' => '订单金额', | 
				
			|||
            'openid' => '用户标识', | 
				
			|||
        ]; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,73 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
use App\Constants\ErrorCode; | 
				
			|||
use League\Flysystem\FilesystemNotFoundException; | 
				
			|||
 | 
				
			|||
class AttachmentService implements AttachmentServiceInterface | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function formUpload($file, $path, $filesystem, $attachmenttype = 'image') | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        $fileRealPath = $file->getRealPath(); | 
				
			|||
        $fileHash = md5_file($fileRealPath); | 
				
			|||
 | 
				
			|||
        $path = $this->getBasePath($path, $attachmenttype); | 
				
			|||
        $fileName = $path . '/' . $fileHash . '.' . $file->getExtension(); | 
				
			|||
 | 
				
			|||
        $stream = fopen($fileRealPath, 'r+'); | 
				
			|||
        $filesystem->writeStream($fileName, $stream); | 
				
			|||
        fclose($stream); | 
				
			|||
 | 
				
			|||
        return $fileName; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function base64Upload($contents, $path, $filesystem) | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        preg_match('/^(data:\s*image\/(\w+);base64,)/', $contents, $result); | 
				
			|||
        if (empty($result)) { | 
				
			|||
            throw new FilesystemNotFoundException(ErrorCode::getMessage(ErrorCode::UPLOAD_INVALID),ErrorCode::UPLOAD_INVALID); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $contents = base64_decode(str_replace($result[1], '', $contents)); | 
				
			|||
 | 
				
			|||
        $fileHash = md5($contents); | 
				
			|||
        $path = $this->getBasePath($path); | 
				
			|||
        $fileName = $path . '/' . $fileHash . '.' . $result[2]; | 
				
			|||
 | 
				
			|||
        $filesystem->write($fileName, $contents); | 
				
			|||
 | 
				
			|||
        return $fileName; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    protected function getBasePath($path, $attachmenttype = 'image') | 
				
			|||
    { | 
				
			|||
        switch ($attachmenttype) { | 
				
			|||
            case 'image': | 
				
			|||
                $baseDir = env('IMAGE_BASE', '/attachment/images'); | 
				
			|||
                break; | 
				
			|||
 | 
				
			|||
            case 'file': | 
				
			|||
                $baseDir = env('FILES_BASE', '/attachment/files'); | 
				
			|||
                break; | 
				
			|||
 | 
				
			|||
            default: | 
				
			|||
                $baseDir = env('FILES_BASE', '/attachment'); | 
				
			|||
                break; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $path = $path ? '/'.$path : ''; | 
				
			|||
        $path .= '/'.date('Y').'/'.date('m').'/'.date('d'); | 
				
			|||
        return $baseDir.$path; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,23 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
interface AttachmentServiceInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * 表单上传,单文件 | 
				
			|||
     * @param $file | 
				
			|||
     * @param $path | 
				
			|||
     * @param $filesystem | 
				
			|||
     * @param string $attachmenttype | 
				
			|||
     */ | 
				
			|||
    public function formUpload($file, $path, $filesystem, $attachmenttype = 'image'); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * base64code上传,单文件 | 
				
			|||
     * @param $contents | 
				
			|||
     * @param $path | 
				
			|||
     * @param $filesystem | 
				
			|||
     */ | 
				
			|||
    public function base64Upload($contents, $path, $filesystem); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,136 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
use App\Commons\Log; | 
				
			|||
use App\Constants\LogLabel; | 
				
			|||
use App\Model\Order; | 
				
			|||
use App\Model\SpeakerDevic; | 
				
			|||
use App\Model\Store; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
use Hyperf\Utils\ApplicationContext; | 
				
			|||
use App\TaskWorker\AliIotTask; | 
				
			|||
 | 
				
			|||
class DeviceServiceImp implements DeviceServiceInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var Log | 
				
			|||
     */ | 
				
			|||
    protected $log; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var IOTServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $IOTService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 获取绑定列表 | 
				
			|||
     * @param $store_id | 
				
			|||
     * @return \Hyperf\Database\Model\Builder[]|\Hyperf\Database\Model\Collection | 
				
			|||
     */ | 
				
			|||
    public function getListByStoreId($store_id) | 
				
			|||
    { | 
				
			|||
        return SpeakerDevic::query()->where(['store_id' => $store_id, 'is_bind' => SpeakerDevic::IS_BIND_YES])->get()->toArray(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 绑定 | 
				
			|||
     * @param $dev_name | 
				
			|||
     * @param $store_id | 
				
			|||
     * @return SpeakerDevic|null | 
				
			|||
     * @throws \Throwable | 
				
			|||
     */ | 
				
			|||
    public function bindByStoreId($dev_name, $store_id) | 
				
			|||
    { | 
				
			|||
        $sd = null; | 
				
			|||
 | 
				
			|||
        if ($this->checkDeviceEnable($dev_name)) { | 
				
			|||
            return $sd; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        try { | 
				
			|||
 | 
				
			|||
            // 获取市场ID
 | 
				
			|||
            $market_id = Store::query()->where(['id' => $store_id])->value('market_id'); | 
				
			|||
 | 
				
			|||
            $sd = SpeakerDevic::query()->updateOrCreate( | 
				
			|||
                ['store_id' => $store_id, 'device_name' => $dev_name], | 
				
			|||
                ['market_id' => $market_id, 'bind_time' => time(), 'is_bind' => SpeakerDevic::IS_BIND_YES] | 
				
			|||
            ); | 
				
			|||
 | 
				
			|||
        } catch (Exception $e) { | 
				
			|||
            $this->log->event(LogLabel::DEVICE_LOG, ['msg' => '绑定设备异常:'.$e->getMessage()]); | 
				
			|||
        } | 
				
			|||
        return $sd; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 解绑 | 
				
			|||
     * @param $bind_id | 
				
			|||
     * @return int | 
				
			|||
     */ | 
				
			|||
    public function unbindById($bind_id) | 
				
			|||
    { | 
				
			|||
        return SpeakerDevic::query()->where(['id' => $bind_id])->update(['is_bind' => SpeakerDevic::IS_BIND_NO]); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 发布语音消息 | 
				
			|||
     * @param $dev_names | 
				
			|||
     * @param $msg | 
				
			|||
     * @return bool | 
				
			|||
     */ | 
				
			|||
    public function pubMsgToStoreByDevName($dev_names, $msg) | 
				
			|||
    { | 
				
			|||
        foreach ($dev_names as $key => $dev_name) { | 
				
			|||
            $this->IOTService->pub($dev_name['device_name'], $msg); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function pubMsgToStoreByOrderMainId($order_id, $is_main = true) | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        // 获取订单
 | 
				
			|||
        $orders = Order::query()->select(['id','order_num','money', 'pay_type', 'store_id', 'type']); | 
				
			|||
        if ($is_main) { | 
				
			|||
            $orders = $orders->where(['order_main_id' => $order_id])->get()->toArray(); | 
				
			|||
        } else { | 
				
			|||
            $orders = $orders->where(['id' => $order_id])->get()->toArray(); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if(empty($orders)) return; | 
				
			|||
 | 
				
			|||
        // 循环发送
 | 
				
			|||
        foreach ($orders as $k => &$order) { | 
				
			|||
 | 
				
			|||
            $device_names = SpeakerDevic::query() | 
				
			|||
                ->select(['device_name']) | 
				
			|||
                ->where(['store_id' => $order['store_id'], 'is_bind' => SpeakerDevic::IS_BIND_YES]) | 
				
			|||
                ->get() | 
				
			|||
                ->toArray(); | 
				
			|||
 | 
				
			|||
            $msg = "{\"msg\":\"到账".$order['money']."元\"}"; | 
				
			|||
            foreach ($device_names as $key => $dev_name) { | 
				
			|||
                $this->IOTService->pub($dev_name['device_name'], $msg); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return true; | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 当前设备是否已经被绑定 | 
				
			|||
     * @param $dev_name | 
				
			|||
     * @return bool | 
				
			|||
     */ | 
				
			|||
    protected function checkDeviceEnable($dev_name) | 
				
			|||
    { | 
				
			|||
        return SpeakerDevic::query()->where(['device_name' => $dev_name, 'is_bind' => SpeakerDevic::IS_BIND_YES])->exists(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,12 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
interface DeviceServiceInterface | 
				
			|||
{ | 
				
			|||
    public function getListByStoreId($store_id); | 
				
			|||
    public function bindByStoreId($dev_name,$store_id); | 
				
			|||
    public function unbindById($bind_id); | 
				
			|||
    public function pubMsgToStoreByDevName($dev_names,$msg); | 
				
			|||
    public function pubMsgToStoreByOrderMainId($order_id, $is_main = true); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,232 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
use App\Libs\FeiePrintClient; | 
				
			|||
use App\Model\OrderMain; | 
				
			|||
use Hyperf\DbConnection\Db; | 
				
			|||
use Hyperf\Utils\ApplicationContext; | 
				
			|||
 | 
				
			|||
class FeiePrintService implements FeiePrintServiceInterface | 
				
			|||
{ | 
				
			|||
    // *必填*:飞鹅云后台注册账号
 | 
				
			|||
    const  USER = '13161443713@163.com'; | 
				
			|||
    // *必填*: 飞鹅云后台注册账号后生成的UKEY 【备注:这不是填打印机的KEY】
 | 
				
			|||
    const  UKEY = 'XsaHzgePdyWTfcMX'; | 
				
			|||
    // *必填*:打印机编号,必须要在管理后台里添加打印机或调用API接口添加之后,才能调用API
 | 
				
			|||
    const  SN = '550510805'; | 
				
			|||
 | 
				
			|||
    // 以下参数不需要修改
 | 
				
			|||
    // 接口IP或域名
 | 
				
			|||
    const  IP = 'api.feieyun.cn'; | 
				
			|||
    // 接口IP端口
 | 
				
			|||
    const  PORT = 80; | 
				
			|||
    // 接口路径
 | 
				
			|||
    const  PATH = '/Api/Open/'; | 
				
			|||
 | 
				
			|||
    public function feiePrint($order_num) | 
				
			|||
    { | 
				
			|||
        // TODO 对象数组=》二维数组
 | 
				
			|||
        $data = Db::table('ims_cjdc_order_main as m') | 
				
			|||
            ->join('ims_cjdc_order as o','o.order_main_id', '=', 'm.id','inner') | 
				
			|||
            ->join('ims_cjdc_order_goods as g','o.id','=', 'g.order_id','inner') | 
				
			|||
            ->join('ims_cjdc_feprint as f','m.market_id','=', 'f.market_id','inner') | 
				
			|||
            ->join('ims_cjdc_store as s','s.id','=', 'o.store_id','inner') | 
				
			|||
            ->where('m.global_order_id', $order_num) | 
				
			|||
            ->selectRaw("o.note as o_note,g.name,g.number,g.money,g.good_unit,m.delivery_time as ps_time,m.address,m.note,m.name as user_name,m.dada_fee,m.money as m_money,m.yhq_money2,m.box_money,f.sn,m.tel,m.order_num,g.id,g.spec,s.name as shopname") | 
				
			|||
            ->orderBy('s.id') | 
				
			|||
            ->get() | 
				
			|||
            ->toArray(); | 
				
			|||
        foreach ($data as $key => &$item) { | 
				
			|||
            $item = (array)$item; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $content = $this->printFormat($data, 14, 6, 3, 6); | 
				
			|||
        $res = $this->printMsg($data[0]['sn'], $content, 1); | 
				
			|||
        return ($res); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * [打印订单接口 Open_printMsg] | 
				
			|||
     * @param  [string] $sn      [打印机编号sn] | 
				
			|||
     * @param  [string] $content [打印内容] | 
				
			|||
     * @param  [string] $times   [打印联数] | 
				
			|||
     * @return [string]          [接口返回值] | 
				
			|||
     */ | 
				
			|||
    protected function printMsg($sn, $content, $times = 1) | 
				
			|||
    { | 
				
			|||
        $time = time();         //请求时间
 | 
				
			|||
        $msgInfo = array( | 
				
			|||
            'user' => self::USER, | 
				
			|||
            'stime' => $time, | 
				
			|||
            'sig' => sha1(self::USER . self::UKEY . $time), | 
				
			|||
            'apiname' => 'Open_printMsg', | 
				
			|||
            'sn' => $sn, | 
				
			|||
            'content' => $content, | 
				
			|||
            'times' => $times//打印次数
 | 
				
			|||
        ); | 
				
			|||
 | 
				
			|||
        $client = new FeiePrintClient(self::IP, self::PORT); | 
				
			|||
        if (!$client->post(self::PATH, $msgInfo)) { | 
				
			|||
            echo 'error'; | 
				
			|||
        } else { | 
				
			|||
            // 服务器返回的JSON字符串,建议要当做日志记录起来
 | 
				
			|||
            $result = $client->getContent(); | 
				
			|||
            return $result; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    protected function printFormat($arr, $A, $B, $C, $D) | 
				
			|||
    { | 
				
			|||
        $orderInfo = '<CB>懒族生活</CB><BR>'; | 
				
			|||
        $orderInfo .= '名称           单价  数量 金额<BR>'; | 
				
			|||
        $orderInfo .= '--------------------------------<BR>'; | 
				
			|||
        $shopname = ""; | 
				
			|||
        $shopnum = 0; | 
				
			|||
        foreach ($arr as $k5 => $v5) { | 
				
			|||
            if ($shopname != $v5['shopname']) { | 
				
			|||
                if ($shopname != "") { | 
				
			|||
                    $orderInfo .= '                                <BR>'; | 
				
			|||
                } | 
				
			|||
                $shopnum++; | 
				
			|||
                $orderInfo .= "<C>(" . $shopnum . ")" .$v5['shopname'] . '</C><BR>'; | 
				
			|||
                $shopname = $v5['shopname']; | 
				
			|||
            } | 
				
			|||
            $name = $v5['name']; | 
				
			|||
            if(!empty($v5['spec'])) { | 
				
			|||
                $name .= "(规格:". $v5['spec'].")"; | 
				
			|||
            }elseif (!empty($v5['good_unit'])){ | 
				
			|||
                $name .= "(规格:". $v5['good_unit'].")"; | 
				
			|||
            } | 
				
			|||
            $price = $v5['money']; | 
				
			|||
            $num = $v5['number']; | 
				
			|||
            $prices = sprintf("%.2f",$v5['money']*$v5['number']); | 
				
			|||
            $kw3 = ''; | 
				
			|||
            $kw1 = ''; | 
				
			|||
            $kw2 = ''; | 
				
			|||
            $kw4 = ''; | 
				
			|||
            $str = $name; | 
				
			|||
            $blankNum = $A;//名称控制为14个字节
 | 
				
			|||
            $lan = mb_strlen($str,'utf-8'); | 
				
			|||
            $m = 0; | 
				
			|||
            $j=1; | 
				
			|||
            $blankNum++; | 
				
			|||
            $result = array(); | 
				
			|||
            if(strlen($price) < $B){ | 
				
			|||
                $k1 = $B - strlen($price); | 
				
			|||
                for($q=0;$q<$k1;$q++){ | 
				
			|||
                    $kw1 .= ' '; | 
				
			|||
                } | 
				
			|||
                $price = $kw1.$price; | 
				
			|||
            } | 
				
			|||
            if(strlen($num) < $C){ | 
				
			|||
                $k2 = $C - strlen($num); | 
				
			|||
                for($q=0;$q<$k2;$q++){ | 
				
			|||
                    $kw2 .= ' '; | 
				
			|||
                } | 
				
			|||
                $num = $kw2.$num; | 
				
			|||
            } | 
				
			|||
            if(strlen($prices) < $D){ | 
				
			|||
                $k3 = $D - strlen($prices); | 
				
			|||
                for($q=0;$q<$k3;$q++){ | 
				
			|||
                    $kw4 .= ' '; | 
				
			|||
                } | 
				
			|||
                $prices = $kw4.$prices; | 
				
			|||
            } | 
				
			|||
            for ($i=0;$i<$lan;$i++){ | 
				
			|||
                $new = mb_substr($str,$m,$j,'utf-8'); | 
				
			|||
                $j++; | 
				
			|||
                if(mb_strwidth($new,'utf-8')<$blankNum) { | 
				
			|||
                    if($m+$j>$lan) { | 
				
			|||
                        $m = $m+$j; | 
				
			|||
                        $tail = $new; | 
				
			|||
                        // $lenght = iconv("UTF-8", "GBK//IGNORE", $new);
 | 
				
			|||
                        $k = $A - mb_strwidth($new,'utf-8'); | 
				
			|||
                        for($q=0;$q<$k;$q++){ | 
				
			|||
                            $kw3 .= ' '; | 
				
			|||
                        } | 
				
			|||
                        if($m==$j){ | 
				
			|||
                            $tail .= $kw3.' '.$price.' '.$num.' '.$prices; | 
				
			|||
                        }else{ | 
				
			|||
                            $tail .= $kw3.'<BR>'; | 
				
			|||
                        } | 
				
			|||
                        break; | 
				
			|||
                    }else{ | 
				
			|||
                        $next_new = mb_substr($str,$m,$j,'utf-8'); | 
				
			|||
                        if(mb_strwidth($next_new,'utf-8')<$blankNum) continue; | 
				
			|||
                        else{ | 
				
			|||
                            $m = $i+1; | 
				
			|||
                            $result[] = $new; | 
				
			|||
                            $j=1; | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
            $head = ''; | 
				
			|||
            foreach ($result as $key=>$value) { | 
				
			|||
                if($key < 1){ | 
				
			|||
                    // $v_lenght = iconv("UTF-8", "GBK//IGNORE", $value);
 | 
				
			|||
                    $v_lenght = mb_strwidth($value,'utf-8'); | 
				
			|||
                    if($v_lenght == 13) $value = $value." "; | 
				
			|||
                    $head .= $value.' '.$price.' '.$num.' '.$prices; | 
				
			|||
                }else{ | 
				
			|||
                    $head .= $value.'<BR>'; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
            $orderInfo .= $head.$tail; | 
				
			|||
            if(!empty($v5['o_note'])){ | 
				
			|||
                $orderInfo .= '备注:'.$v5['o_note'].'<BR>'; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        // $time = date('Y-m-d H:i:s', time());
 | 
				
			|||
        $orderInfo .= '--------------------------------<BR>'; | 
				
			|||
        if ($arr[0]['box_money'] > 0) { | 
				
			|||
            $kw5 = ''; | 
				
			|||
            $len = 24 - strlen($arr[0]['box_money']); | 
				
			|||
            for ($q = 0; $q < $len; $q++) { | 
				
			|||
                $kw5 .= ' '; | 
				
			|||
            } | 
				
			|||
            $orderInfo .= '包装费:' . $kw5 . $arr[0]['box_money'] . '<BR>'; | 
				
			|||
        } | 
				
			|||
        if($arr[0]['dada_fee'] > 0){ | 
				
			|||
            $kw5 = ''; | 
				
			|||
            $len = 24 - strlen($arr[0]['dada_fee']); | 
				
			|||
            for ($q = 0; $q < $len; $q++) { | 
				
			|||
                $kw5 .= ' '; | 
				
			|||
            } | 
				
			|||
            $orderInfo .= '配送费:'.$kw5.$arr[0]['dada_fee'].'<BR>'; | 
				
			|||
        } | 
				
			|||
        if($arr[0]['yhq_money2'] > 0){ | 
				
			|||
            $yhq_money2 = sprintf("%.2f",$arr[0]['yhq_money2']); | 
				
			|||
            $kw6 = ''; | 
				
			|||
            $len = 25 - strlen($yhq_money2); | 
				
			|||
            for ($q = 0; $q < $len; $q++) { | 
				
			|||
                $kw6 .= ' '; | 
				
			|||
            } | 
				
			|||
            $orderInfo .= '红包:'.$kw6.'-'.$yhq_money2.'<BR>'; | 
				
			|||
        } | 
				
			|||
        $total = '合计:'.$arr[0]['m_money']; | 
				
			|||
        $user_name = $arr[0]['user_name']; | 
				
			|||
        if(strlen($user_name)>18){ | 
				
			|||
            $user_name=substr($user_name,0,18).'...'; | 
				
			|||
        } | 
				
			|||
        $str = $user_name . $total; | 
				
			|||
        $kw5 = ''; | 
				
			|||
        // $lenght = iconv("UTF-8", "GBK//IGNORE", $str);
 | 
				
			|||
        $total_len = 32 - mb_strwidth($str,'utf-8'); | 
				
			|||
        for ($q = 0; $q < $total_len; $q++) { | 
				
			|||
            $kw5 .= ' '; | 
				
			|||
        } | 
				
			|||
        $total_str = $user_name.$kw5.$total; | 
				
			|||
        $orderInfo .= $total_str.'<BR>'; | 
				
			|||
        $orderInfo .= '送货地点:' . $arr[0]['address'] . '<BR>'; | 
				
			|||
        $tel = substr_replace( $arr[0]['tel'], '****', 3, 4); | 
				
			|||
        $orderInfo .= '联系电话:' . $tel . '<BR>'; | 
				
			|||
        $orderInfo .= '配送时间:' . $arr[0]['ps_time'] . '<BR>'; | 
				
			|||
        if(!empty($arr[0]['note'])){ | 
				
			|||
            $orderInfo .= '备注:'.$arr[0]['note'].'<BR><BR>'; | 
				
			|||
        } | 
				
			|||
        //$orderInfo .= '<QR>http://www.feieyun.com</QR>';//把解析后的二维码生成的字符串用标签套上即可自动生成二维码
 | 
				
			|||
        return $orderInfo; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,10 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
interface FeiePrintServiceInterface | 
				
			|||
{ | 
				
			|||
    public function feiePrint($order_num); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,54 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
use AlibabaCloud\Client\AlibabaCloud; | 
				
			|||
use AlibabaCloud\Client\Exception\ClientException; | 
				
			|||
use AlibabaCloud\Client\Exception\ServerException; | 
				
			|||
use App\Commons\Log; | 
				
			|||
use App\Constants\LogLabel; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
 | 
				
			|||
class IOTAliService implements IOTServiceInterface | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var Log | 
				
			|||
     */ | 
				
			|||
    protected $log; | 
				
			|||
 | 
				
			|||
    public function pub($device_name, $msg) | 
				
			|||
    { | 
				
			|||
        AlibabaCloud::accessKeyClient(env('ALI_IOT_KEY'), env('ALI_IOT_SECRET')) | 
				
			|||
            ->regionId(env('ALI_IOT_REGION')) | 
				
			|||
            ->asDefaultClient(); | 
				
			|||
 | 
				
			|||
        try { | 
				
			|||
            AlibabaCloud::rpc() | 
				
			|||
                ->product('Iot') | 
				
			|||
                ->version('2018-01-20') | 
				
			|||
                ->action('Pub') | 
				
			|||
                ->method('POST') | 
				
			|||
                ->host(env('ALI_IOT_HOST')) | 
				
			|||
                ->options([ | 
				
			|||
                    'query' => [ | 
				
			|||
                        'RegionId' => "cn-shanghai", | 
				
			|||
                        'TopicFullName' => "/".env('ALI_IOT_PRODUCT_KEY')."/".$device_name."/user/get", | 
				
			|||
                        'MessageContent' => base64_encode($msg), | 
				
			|||
                        'ProductKey' => env('ALI_IOT_PRODUCT_KEY'), | 
				
			|||
                    ], | 
				
			|||
                ]) | 
				
			|||
                ->request(); | 
				
			|||
        } catch (ClientException $e) { | 
				
			|||
            $this->log->event(LogLabel::DEVICE_LOG, ['msg' => 'ClientException发布失败:'.$e->getErrorMessage()]); | 
				
			|||
            return false; | 
				
			|||
        } catch (ServerException $e) { | 
				
			|||
            $this->log->event(LogLabel::DEVICE_LOG, ['msg' => 'ServerException发布失败:'.$e->getErrorMessage()]); | 
				
			|||
            return false; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,8 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
interface IOTServiceInterface | 
				
			|||
{ | 
				
			|||
    public function pub($device_name, $msg); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,209 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
use App\Model\Order; | 
				
			|||
use App\Model\OrderGoods; | 
				
			|||
use App\Model\OrderMain; | 
				
			|||
use App\Model\Store; | 
				
			|||
use App\Model\Users; | 
				
			|||
use EasyWeChat\Factory; | 
				
			|||
use Hyperf\Guzzle\CoroutineHandler; | 
				
			|||
 | 
				
			|||
class MiniprogramService implements MiniprogramServiceInterface | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function sendTemMsgForOnlineOrder($order_main_id) | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        // 查询订单信息
 | 
				
			|||
        $order = OrderMain::find($order_main_id); | 
				
			|||
 | 
				
			|||
        $payTypes = ['1' => '微信支付', '2' => '余额支付', '3' => '积分支付', '4' => '货到付款']; | 
				
			|||
        $address_store = $order['address'] . ';' .$order['name']. ';'. substr_replace($order['tel'],'****',3,4); | 
				
			|||
        $address = $order['address'] . ';' .$order['name']. ';'. $order['tel']; | 
				
			|||
 | 
				
			|||
        // 查询子订单,用于发消息给商户
 | 
				
			|||
        $order_children = Order::query()->select(['id', 'order_num', 'store_id', 'money', 'time']) | 
				
			|||
            ->where(['order_main_id' => $order_main_id]) | 
				
			|||
            ->get() | 
				
			|||
            ->toArray(); | 
				
			|||
 | 
				
			|||
        $goods_temp_all = []; | 
				
			|||
        foreach ($order_children as $key => &$item) { | 
				
			|||
 | 
				
			|||
            // 订单商品
 | 
				
			|||
            $order_goods = OrderGoods::query()->select(['name', 'number', 'spec', 'good_unit']) | 
				
			|||
                ->where(['order_id' => $item['id']]) | 
				
			|||
                ->get() | 
				
			|||
                ->toArray(); | 
				
			|||
 | 
				
			|||
            $goods_temp = []; | 
				
			|||
            foreach ($order_goods as $k => &$goods) { | 
				
			|||
                array_push($goods_temp, $goods['name']."*".$goods['number']."/".($goods['spec']?:$goods['good_unit'])); | 
				
			|||
                array_push($goods_temp_all, $goods['name']."*".$goods['number']."/".($goods['spec']?:$goods['good_unit'])); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 商户/门店的openid
 | 
				
			|||
            $store = Store::query()->select(['id', 'name', 'user_id']) | 
				
			|||
                ->where(['id' => $item['store_id']]) | 
				
			|||
                ->first()->toArray(); | 
				
			|||
            $store['openid'] = Users::query() | 
				
			|||
                ->where(['id' => $store['user_id']]) | 
				
			|||
                ->value('openid'); | 
				
			|||
 | 
				
			|||
            // 模板数据
 | 
				
			|||
            $data_store = [ | 
				
			|||
                'first' => ['您有新的外卖订单!订单编号:'.$item['order_num'], '#ff0000'], | 
				
			|||
                'keyword' => [ | 
				
			|||
                    ["您的外卖订单详情:\r\n".implode(";\r\n",$goods_temp), '#ff0000'], | 
				
			|||
                    $item['money'], | 
				
			|||
                    $payTypes[$order['pay_type']], | 
				
			|||
                    $item['time']?:'', | 
				
			|||
                    $address_store, | 
				
			|||
                ], | 
				
			|||
                'remark' => [$order['note'], '#4e6ef2'] | 
				
			|||
            ]; | 
				
			|||
 | 
				
			|||
            $ret_store = $this->sendTempMsg($store['openid'], '-M7DG_ACwJxqdAvyvJuAnPpx4xaLf3VkkN0fckno71c',$data_store); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // 模板数据发送消息给用户
 | 
				
			|||
        $data_user = [ | 
				
			|||
            'first' => '您好,下单成功!订单编号:'.$order['order_num'], | 
				
			|||
            'keyword' => [ | 
				
			|||
                implode(";\r\n", $goods_temp_all), | 
				
			|||
                $order['money'], | 
				
			|||
                $payTypes[$order['pay_type']], | 
				
			|||
                date('Y-m-d H:i:s', $order['time_add']), | 
				
			|||
                $address, | 
				
			|||
            ], | 
				
			|||
            'remark' => '感谢您的光临,欢迎下次再来!' | 
				
			|||
        ]; | 
				
			|||
 | 
				
			|||
        // 获取用户openid,发送给用户
 | 
				
			|||
        $user_openid = Users::query()->where(['id' => $order['user_id']])->value('openid'); | 
				
			|||
        $ret_user = $this->sendTempMsg($user_openid,'-M7DG_ACwJxqdAvyvJuAnPpx4xaLf3VkkN0fckno71c', $data_user); | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function sendTemMsgForOfflineOrder($order_main_id) | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        // 查询子订单,用于发消息给商户
 | 
				
			|||
        $order_children = Order::query()->select(['id', 'order_num', 'store_id', 'money', 'time']) | 
				
			|||
            ->where(['order_main_id' => $order_main_id]) | 
				
			|||
            ->get() | 
				
			|||
            ->toArray(); | 
				
			|||
 | 
				
			|||
        foreach ($order_children as $key => &$item) { | 
				
			|||
            // 商户/门店的openid
 | 
				
			|||
            $store = Store::query()->select(['id', 'name', 'user_id']) | 
				
			|||
                ->where(['id' => $item['store_id']]) | 
				
			|||
                ->first()->toArray(); | 
				
			|||
            $store['openid'] = Users::query() | 
				
			|||
                ->where(['id' => $store['user_id']]) | 
				
			|||
                ->value('openid'); | 
				
			|||
 | 
				
			|||
            // 模板数据
 | 
				
			|||
            $data_store = [ | 
				
			|||
                'first' => '您有新订单收入!订单编号:'.$item['order_num'], | 
				
			|||
                'keyword' => [ | 
				
			|||
                    $store['name']?:'', | 
				
			|||
                    $item['time']?:'', | 
				
			|||
                    '暂无', | 
				
			|||
                    $item['money'] | 
				
			|||
                ], | 
				
			|||
                'remark' => '感谢您的使用!' | 
				
			|||
            ]; | 
				
			|||
 | 
				
			|||
            $ret_store = $this->sendTempMsg($store['openid'], 'lxVbC6PVpKbiO44bYqLmacl-BaME70D47Q0jn2Link0',$data_store); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function sendTemMsgForAward($money, $note, $openid, $time) | 
				
			|||
    { | 
				
			|||
        // 模板数据发送消息给用户
 | 
				
			|||
        $data_user = [ | 
				
			|||
            'first' => '恭喜!您有一笔新的奖励收入!', | 
				
			|||
            'keyword' => [ | 
				
			|||
                $money, | 
				
			|||
                $note, | 
				
			|||
                $time | 
				
			|||
            ], | 
				
			|||
            'remark' => '感谢您的使用!' | 
				
			|||
        ]; | 
				
			|||
 | 
				
			|||
        // 获取用户openid,发送给用户
 | 
				
			|||
        $ret_user = $this->sendTempMsg($openid,'ypZ7xdHUjWrRG8P-MD42dhpp6kUlh4Unoh7eTSrLZEg', $data_user); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function sendTempMsg($openid, $template_id, $data, $redirect_url = '', $applet_config = ['appid' => '', 'pagepath' => '']) | 
				
			|||
    { | 
				
			|||
        // 先拼个基础的
 | 
				
			|||
        $template = [ | 
				
			|||
            'touser' => $openid, | 
				
			|||
            'mp_template_msg' => [ | 
				
			|||
                'appid'         => env('OFFICIAL_APP_ID'), | 
				
			|||
                'template_id'   => $template_id, | 
				
			|||
                'url'           => $redirect_url, | 
				
			|||
            ] | 
				
			|||
        ]; | 
				
			|||
 | 
				
			|||
        // 看看有没有小程序跳转的要求
 | 
				
			|||
        $template['mp_template_msg']['miniprogram'] = $applet_config; | 
				
			|||
 | 
				
			|||
        // 重点来了,拼接关键数据data
 | 
				
			|||
        if (!is_array($data)) { # 数组都不是,请回去
 | 
				
			|||
            return false; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (is_array($data['first'])) { | 
				
			|||
            $template['mp_template_msg']['data']['first']['value'] = $data['first'][0] ?? ''; | 
				
			|||
            $template['mp_template_msg']['data']['first']['color'] = $data['first'][1] ?? ''; | 
				
			|||
        } else { | 
				
			|||
            $template['mp_template_msg']['data']['first']['value'] = $data['first']; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (isset($data['keyword'])&&is_array($data['keyword'])) { | 
				
			|||
            foreach ($data['keyword'] as $key => &$keyword) { | 
				
			|||
                $index = $key+1; | 
				
			|||
 | 
				
			|||
                if (is_array($keyword)) { | 
				
			|||
                    $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword[0] ?? ''; | 
				
			|||
                    $template['mp_template_msg']['data']['keyword'.$index]['color'] = $keyword[1] ?? ''; | 
				
			|||
                } else { | 
				
			|||
                    $template['mp_template_msg']['data']['keyword'.$index]['value'] = $keyword; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (is_array($data['remark'])) { | 
				
			|||
            $template['mp_template_msg']['data']['remark']['value'] = $data['remark'][0] ?? ''; | 
				
			|||
            $template['mp_template_msg']['data']['remark']['color'] = $data['remark'][1] ?? ''; | 
				
			|||
        } else { | 
				
			|||
            $template['mp_template_msg']['data']['remark']['value'] = $data['remark']; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $app = Factory::miniProgram(config('wxtempmsg')); | 
				
			|||
        $app['guzzle_handler'] = CoroutineHandler::class; | 
				
			|||
        $app->uniform_message->send($template); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,41 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
interface MiniprogramServiceInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * 外卖线上订单模板消息 | 
				
			|||
     * @param $order_main_id | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function sendTemMsgForOnlineOrder($order_main_id); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 当面线下订单模板消息 | 
				
			|||
     * @param $order_main_id | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function sendTemMsgForOfflineOrder($order_main_id); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 奖励模板消息 | 
				
			|||
     * @param $money | 
				
			|||
     * @param $note | 
				
			|||
     * @param $openid | 
				
			|||
     * @param $time | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function sendTemMsgForAward($money, $note, $openid, $time); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 发送模板消息 | 
				
			|||
     * @param $openid | 
				
			|||
     * @param $template_id | 
				
			|||
     * @param $data | 
				
			|||
     * @param string $redirect_url | 
				
			|||
     * @param string[] $applet_config | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function sendTempMsg($openid, $template_id, $data, $redirect_url = '', $applet_config = ['appid' => '', 'pagepath' => '']); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,29 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
interface MqttServiceInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * 发布给商户 | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function speakToStore($orderId, $isMain = true); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @param string|number $message 消息内容 | 
				
			|||
     * @param string $topic 发布消息到主题,主题名 | 
				
			|||
     * @param string $type 消息类型,cash或tts | 
				
			|||
     * @param string $payId 支付方式,如“支付宝”、“微信”等 | 
				
			|||
     * @param string $toClientId 终端id,如IMEI码 | 
				
			|||
     * @param string $curClientId 当前客户端id | 
				
			|||
     */ | 
				
			|||
    public function publish( | 
				
			|||
        $message, | 
				
			|||
        $topic, | 
				
			|||
        $toClientId = '', | 
				
			|||
        $type = '', | 
				
			|||
        $payId = '', | 
				
			|||
        $curClientId = '' | 
				
			|||
    ); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,81 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
use App\Libs\MQTTClient; | 
				
			|||
use App\Model\Order; | 
				
			|||
use App\Model\Store; | 
				
			|||
use Hyperf\Utils\ApplicationContext; | 
				
			|||
 | 
				
			|||
class MqttSpeakerService implements MqttServiceInterface | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    const TOPIC = 'test01'; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function speakToStore($orderId, $isMain = true) | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        // 获取订单
 | 
				
			|||
        $orders = Order::query()->select(['id','order_num','money', 'pay_type', 'store_id', 'type']); | 
				
			|||
        if ($isMain) { | 
				
			|||
            $orders = $orders->where(['order_main_id' => $orderId])->get()->toArray(); | 
				
			|||
        } else { | 
				
			|||
            $orders = $orders->where(['id' => $orderId])->get()->toArray(); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if(empty($orders)) return; | 
				
			|||
 | 
				
			|||
        // 循环发送
 | 
				
			|||
        foreach ($orders as $k => &$order) { | 
				
			|||
            $order['template'] = "懒族支付到账".floatval($order['money'])."元"; | 
				
			|||
            // 获取终端ID
 | 
				
			|||
            $order['to_client_id'] = Store::query()->where(['id' => $order['store_id']])->value('loudspeaker_imei'); | 
				
			|||
            // 发布订阅消息
 | 
				
			|||
            $res = $this->publish($order['template'], self::TOPIC, $order['to_client_id']); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function publish( | 
				
			|||
        $message, | 
				
			|||
        $topic, | 
				
			|||
        $toClientId = '', | 
				
			|||
        $type = '', | 
				
			|||
        $payId = '', | 
				
			|||
        $curClientId = '' | 
				
			|||
    ) { | 
				
			|||
 | 
				
			|||
        $client = new MQTTClient(env('MQTT_HOST'), env('MQTT_PORT')); | 
				
			|||
        $client->setAuthentication(env('MQTT_NAME'), env('MQTT_PASS')); | 
				
			|||
        $client->setDebug(true); | 
				
			|||
 | 
				
			|||
        if (env('MQTT_CERT')) { | 
				
			|||
            $client->setEncryption(env('MQTT_CERT')); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $msgArr = []; | 
				
			|||
        if ( (empty($type)&&is_numeric($message)) || 'cash' === $type ) { | 
				
			|||
            $msgArr['cash'] = $message; | 
				
			|||
            $payId AND $msgArr['payid'] = $payId; | 
				
			|||
        } else { | 
				
			|||
            $msgArr['message'] = $message; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (!empty($toClientId)) { | 
				
			|||
            $topic .= '/'.$toClientId; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $curClientId OR $curClientId = (string)rand(1,999999999); | 
				
			|||
        $success = $client->sendConnect($curClientId); | 
				
			|||
        if ($success) { | 
				
			|||
            $client->sendPublish($topic, json_encode($msgArr), MQTTClient::MQTT_QOS2); | 
				
			|||
            $client->sendDisconnect(); | 
				
			|||
        } | 
				
			|||
        $client->close(); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,520 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
use App\Model\Coupon; | 
				
			|||
use App\Model\CouponUserRec; | 
				
			|||
use App\Model\CouponUserUse; | 
				
			|||
use App\Model\Goods; | 
				
			|||
use App\Model\Order; | 
				
			|||
use App\Model\OrderGoods; | 
				
			|||
use App\Model\OrderMain; | 
				
			|||
use App\Model\SpecCombination; | 
				
			|||
use App\Model\Users; | 
				
			|||
use Exception; | 
				
			|||
use Hyperf\DbConnection\Db; | 
				
			|||
use Hyperf\Snowflake\IdGeneratorInterface; | 
				
			|||
use Hyperf\Utils\ApplicationContext; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
 | 
				
			|||
class OrderService implements OrderServiceInterface | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var CouponServiceInterface | 
				
			|||
     */ | 
				
			|||
    protected $couponService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function addOnlineOrder($data) | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        bcscale(6); | 
				
			|||
 | 
				
			|||
        // 订单判重
 | 
				
			|||
        $dataMain = $data; | 
				
			|||
 | 
				
			|||
        if ($orderMainId = $this->existsByOrderNum($data['order_num'])) { | 
				
			|||
            return $orderMainId; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        Db::beginTransaction(); | 
				
			|||
        try { | 
				
			|||
 | 
				
			|||
            // 计算当前订单可用红包优惠金额
 | 
				
			|||
            $couponMoney = 0; | 
				
			|||
            $receiveCouponIds = []; | 
				
			|||
            if (isset($data['receive_coupon_ids'])&&$data['receive_coupon_ids']) { | 
				
			|||
                $receiveCouponIds = explode(',', str_replace(',',',',$data['receive_coupon_ids'])); | 
				
			|||
                $couponMoney = $this->getCouponAmount($receiveCouponIds, $data['money'], $data['user_id'], $data['market_id']); | 
				
			|||
            } | 
				
			|||
            $dataMain['yhq_money2'] = $couponMoney; | 
				
			|||
 | 
				
			|||
            // 获取分布式全局ID
 | 
				
			|||
            $generator = ApplicationContext::getContainer()->get(IdGeneratorInterface::class); | 
				
			|||
            $dataMain['global_order_id'] = $generator->generate(); | 
				
			|||
 | 
				
			|||
            // 店铺IDs
 | 
				
			|||
            $dataMain['store_ids'] = ''; | 
				
			|||
            $storeList = json_decode(html_entity_decode($data['store_list']), true); | 
				
			|||
            if (!is_array($storeList)||empty($storeList)) { | 
				
			|||
                Db::rollBack(); | 
				
			|||
                return '订单中商品不存在或已失效'; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 获取商户IDs
 | 
				
			|||
            foreach ($storeList as &$item) { | 
				
			|||
                $dataMain['store_ids'] .= empty($dataMain['store_ids']) ? $item['store_id'] : ','.$item['store_id']; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 主订单插入数据
 | 
				
			|||
            $currentTime = time(); | 
				
			|||
            $dataMain['time'] = date('Y-m-d H:i:s', $currentTime); | 
				
			|||
            $dataMain['time_add'] = $currentTime; | 
				
			|||
            $dataMain['pay_time'] = ''; | 
				
			|||
            $dataMain['state'] = OrderMain::ORDER_STATE_UNPAY; | 
				
			|||
            $dataMain['code'] = $dataMain['global_order_id']; | 
				
			|||
            $dataMain['jj_note'] = ''; | 
				
			|||
 | 
				
			|||
            // 主订单模型保存
 | 
				
			|||
            $orderMain = OrderMain::create($dataMain); | 
				
			|||
            $orderMainId = $orderMain->id; | 
				
			|||
 | 
				
			|||
            // 统计订单中所有店铺当日订单数,做店铺订单序号
 | 
				
			|||
            $countsArr = Order::query() | 
				
			|||
                ->selectRaw('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')]) | 
				
			|||
                ->get() | 
				
			|||
                ->toArray(); | 
				
			|||
 | 
				
			|||
            $storeOrderCounts = []; | 
				
			|||
            foreach ($countsArr as $key => &$row) { | 
				
			|||
                $storeOrderCounts[$row['id']] = $row['count']; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 循环处理订单总额、子订单总额、商品、商户订单等信息
 | 
				
			|||
            $orderAmountTotal = 0; # 总订单金额
 | 
				
			|||
            $orderGoods = []; | 
				
			|||
            foreach ($storeList as $key => &$item) { | 
				
			|||
 | 
				
			|||
                // 子订单数据处理
 | 
				
			|||
                $dataChild = [ | 
				
			|||
                    'uniacid' => $data['uniacid'], | 
				
			|||
                    'order_num' => 's'.date('YmdHis', time()) . rand(1111, 9999), | 
				
			|||
                    'user_id' => $orderMain->user_id, | 
				
			|||
                    'store_id' => $item['store_id'], | 
				
			|||
                    'order_main_id' => $orderMainId, | 
				
			|||
                    'state' => OrderMain::ORDER_STATE_UNPAY, | 
				
			|||
                    'tel' => $orderMain->tel, | 
				
			|||
                    'name' => $orderMain->name, | 
				
			|||
                    'address' => $orderMain->address, | 
				
			|||
                    'area' => $orderMain->area, | 
				
			|||
                    'time' => date("Y-m-d H:i:s"), | 
				
			|||
                    'note' => $item['note'] ?? '', | 
				
			|||
                    'delivery_time' => $orderMain->delivery_time, | 
				
			|||
                    'type' => $orderMain->type, | 
				
			|||
                    'lat' => $orderMain->lat, | 
				
			|||
                    'lng' => $orderMain->lng, | 
				
			|||
                    'pay_type' => $orderMain->pay_type, | 
				
			|||
                    'order_type' => $orderMain->order_type, | 
				
			|||
                    'money' => floatval($item['subtotal']), | 
				
			|||
                    'box_money' => floatval($item['box_money']), | 
				
			|||
                    'mj_money' => floatval($item['mj_money']), | 
				
			|||
                    'yhq_money' => floatval($item['yhq_money']), | 
				
			|||
                    'yhq_money2' => floatval($item['yhq_money2']), | 
				
			|||
                    'zk_money' => floatval($item['zk_money']), | 
				
			|||
                    'coupon_id' => $item['coupon_id'], | 
				
			|||
                    'coupon_id2' => $item['coupon_id2'], | 
				
			|||
                    'xyh_money' => floatval($item['xyh_money']), | 
				
			|||
                    'oid' => (isset($storeOrderCounts[$item['store_id']]) ? $item['store_id'] : 0) + 1, | 
				
			|||
                    'time_add' => date("Y-m-d H:i:s"), | 
				
			|||
                    'jj_note' => '', | 
				
			|||
                    'form_id' => '', | 
				
			|||
                    'form_id2' => '', | 
				
			|||
                    'code' => '', | 
				
			|||
                ]; | 
				
			|||
 | 
				
			|||
                $orderChildId = Order::query()->insertGetId($dataChild); | 
				
			|||
 | 
				
			|||
                // 子订单内商品处理
 | 
				
			|||
                $goodsAmountTotal = 0; | 
				
			|||
 | 
				
			|||
                if (!is_array($item['good_list'])||empty($item['good_list'])) { | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    return '订单商品异常'; | 
				
			|||
                } | 
				
			|||
                foreach ($item['good_list'] as &$goods) { | 
				
			|||
                    $goodsAmount = bcadd(floatval($goods['money']), floatval($goods['box_money'])); | 
				
			|||
                    $goodsAmount = bcmul($goodsAmount, $goods['num']); | 
				
			|||
                    $goodsAmountTotal = bcadd($goodsAmountTotal, $goodsAmount); | 
				
			|||
 | 
				
			|||
                    $orderGoods[$goods['id']] = $goods; | 
				
			|||
                    $orderGoods[$goods['id']]['uniacid'] = $data['uniacid']; | 
				
			|||
                    $orderGoods[$goods['id']]['order_id'] = $orderChildId; | 
				
			|||
                    $orderGoods[$goods['id']]['user_id'] = $dataMain['user_id']; | 
				
			|||
                    $orderGoods[$goods['id']]['store_id'] = $item['store_id']; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                // 子订单优惠总额
 | 
				
			|||
                $discountAmountTotal = bcadd($dataChild['mj_money'], $dataChild['yhq_money']); | 
				
			|||
                $discountAmountTotal = bcadd($discountAmountTotal, $dataChild['yhq_money2']); | 
				
			|||
                $discountAmountTotal = bcadd($discountAmountTotal, $dataChild['zk_money']); | 
				
			|||
                $discountAmountTotal = bcadd($discountAmountTotal, $dataChild['xyh_money']); | 
				
			|||
 | 
				
			|||
                $goodsAmountTotal = bcsub($goodsAmountTotal, $discountAmountTotal, 2); | 
				
			|||
                $orderAmountTotal = bcadd($orderAmountTotal, $goodsAmountTotal, 2); | 
				
			|||
 | 
				
			|||
                // 校验子订单金额
 | 
				
			|||
                if ($goodsAmountTotal != $dataChild['money']) { | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    return '店铺订单总金额错误'; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 校验库存
 | 
				
			|||
            foreach ($orderGoods as $Key => &$goodsItem) { | 
				
			|||
 | 
				
			|||
                $goodsItem['combination_id'] = intval($goodsItem['combination_id']); | 
				
			|||
 | 
				
			|||
                // 存在规格,则去规格处查库存
 | 
				
			|||
                $goods = []; | 
				
			|||
                if ($goodsItem['combination_id'] > 0) { | 
				
			|||
 | 
				
			|||
                    $combination = SpecCombination::query() | 
				
			|||
                        ->select(['good_id AS id', 'number AS inventory']) | 
				
			|||
                        ->where(['id' => $goodsItem['combination_id']]) | 
				
			|||
                        ->first() | 
				
			|||
                        ->toArray(); | 
				
			|||
 | 
				
			|||
                    $goods = Goods::query() | 
				
			|||
                        ->select(['id', 'name', 'is_max']) | 
				
			|||
                        ->where(['id' => $combination['id']]) | 
				
			|||
                        ->first() | 
				
			|||
                        ->toArray(); | 
				
			|||
                    $goods['inventory'] = $combination['inventory']; | 
				
			|||
 | 
				
			|||
                } else { | 
				
			|||
 | 
				
			|||
                    $goods = Goods::query() | 
				
			|||
                        ->select(['id', 'name', 'is_max', 'inventory']) | 
				
			|||
                        ->where(['id' => $goodsItem['good_id']]) | 
				
			|||
                        ->first() | 
				
			|||
                        ->toArray(); | 
				
			|||
 | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                if (!$goods) { | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    return '缺少商品'; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                if($goodsItem['num'] > $goods['inventory'] && $goods['is_max'] != Goods::INVENTORY_NOLIMIT){ | 
				
			|||
                    Db::rollBack(); | 
				
			|||
                    return '商品 '.$goods->name.' 库存不足!'; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 校验总订单金额
 | 
				
			|||
            $deliveryAmount = 0; # 配送费用
 | 
				
			|||
            if($dataMain['order_type'] == OrderMain::ORDER_TYPE_ONLINE){ | 
				
			|||
                $deliveryAmount = $dataMain['dada_fee']; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $orderAmountTotal = bcadd($orderAmountTotal, $deliveryAmount); | 
				
			|||
            # 总订单优惠总额
 | 
				
			|||
            $discountAmountTotal = bcadd($dataMain['mj_money'], $dataMain['yhq_money']); | 
				
			|||
            $discountAmountTotal = bcadd($discountAmountTotal, $dataMain['yhq_money2']); | 
				
			|||
            $discountAmountTotal = bcadd($discountAmountTotal, $dataMain['zk_money']); | 
				
			|||
            $discountAmountTotal = bcadd($discountAmountTotal, $dataMain['xyh_money']); | 
				
			|||
            $orderAmountTotal = bcsub($orderAmountTotal, $discountAmountTotal, 2); | 
				
			|||
 | 
				
			|||
            if ($orderAmountTotal != bcsub(bcadd($dataMain['money'], $deliveryAmount), $discountAmountTotal, 2)) { | 
				
			|||
                Db::rollBack(); | 
				
			|||
                return '订单总金额错误'; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 添加订单商品
 | 
				
			|||
            $tempGoods = $orderGoods; | 
				
			|||
            $orderGoods = []; | 
				
			|||
            foreach ($tempGoods as $key => &$value) { | 
				
			|||
                $goodsTemp['good_id'] = $value['good_id']; | 
				
			|||
                $goodsTemp['img'] = $value['logo']; | 
				
			|||
                $goodsTemp['number'] = $value['num']; | 
				
			|||
                $goodsTemp['order_id'] = $value['order_id']; | 
				
			|||
                $goodsTemp['name'] = $value['name']; | 
				
			|||
                $goodsTemp['money'] = $value['money']; | 
				
			|||
                $goodsTemp['dishes_id'] = $value['dishes_id']; | 
				
			|||
                $goodsTemp['spec'] = $value['spec']; | 
				
			|||
                $goodsTemp['is_qg'] = $value['is_qg']; | 
				
			|||
                $goodsTemp['good_unit'] = $value['good_unit']; | 
				
			|||
                $goodsTemp['uniacid'] = $value['uniacid']; | 
				
			|||
                $goodsTemp['combination_id'] = $value['combination_id']; | 
				
			|||
                $orderGoods[] = $goodsTemp; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $addOrderGoods = OrderGoods::query()->insert($orderGoods); | 
				
			|||
            if (!$addOrderGoods) { | 
				
			|||
                Db::rollBack(); | 
				
			|||
                return '订单商品异常'; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 修改总订单金额,金额是计算来的
 | 
				
			|||
            // TODO 这部分其实可以结合处理优化一下,循环前后关联处理太多
 | 
				
			|||
            $updateOrderMain = OrderMain::query()->where(['id' => $orderMainId])->update(['money' => $orderAmountTotal, 'total_money' => $dataMain['money']]); | 
				
			|||
            if (!$updateOrderMain) { | 
				
			|||
                Db::rollBack(); | 
				
			|||
                return '订单总金额记录失败'; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // 处理红包的使用
 | 
				
			|||
            $canUseCoupons = CouponUserRec::select(['id', 'user_id', 'number', 'number_remain', 'system_coupon_user_id']) | 
				
			|||
                ->whereIn('id', $receiveCouponIds) | 
				
			|||
                ->get()->toArray(); | 
				
			|||
            if (is_array($canUseCoupons)&&!empty($canUseCoupons)) { | 
				
			|||
                # 使用记录、更新当前优惠券
 | 
				
			|||
                foreach ($canUseCoupons as $key => &$coupon) { | 
				
			|||
 | 
				
			|||
                    $couponUse = [ | 
				
			|||
                        'user_id' => $coupon['user_id'], | 
				
			|||
                        'user_receive_id' => $coupon['id'], | 
				
			|||
                        'system_coupon_id' => $coupon['system_coupon_user_id'], | 
				
			|||
                        'order_main_id' => $orderMainId, | 
				
			|||
                        'use_time' => $currentTime, | 
				
			|||
                        'return_time' => 0, | 
				
			|||
                        'number' => 1, | 
				
			|||
                        'status' => 1, | 
				
			|||
                        'update_time' => 0, | 
				
			|||
                    ]; | 
				
			|||
                    var_dump('$couponUse',$couponUse); | 
				
			|||
 | 
				
			|||
                    $insertRes = CouponUserUse::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 = CouponUserRec::query()->where(['id' => $coupon['id']])->update(['number_remain' => $numberRemain, 'status' => $status]); | 
				
			|||
 | 
				
			|||
                        if (!$upRes) { | 
				
			|||
                            Db::rollBack(); | 
				
			|||
                            return '优惠券使用失败'; | 
				
			|||
                        } | 
				
			|||
 | 
				
			|||
                        // 缓存使用记录
 | 
				
			|||
                        $usedRes = $this->couponService->cacheTodayCouponUsed($coupon['user_id'], $coupon['system_coupon_user_id'], $coupon['id']); | 
				
			|||
                        if (!$usedRes) { | 
				
			|||
                            Db::rollBack(); | 
				
			|||
                            return '优惠券使用失败'; | 
				
			|||
                        } | 
				
			|||
 | 
				
			|||
                    } else { | 
				
			|||
                        Db::rollBack(); | 
				
			|||
                        return '优惠券使用失败'; | 
				
			|||
                    } | 
				
			|||
 | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            Db::commit(); | 
				
			|||
            return $orderMainId; | 
				
			|||
 | 
				
			|||
        } catch (Exception $e) { | 
				
			|||
 | 
				
			|||
            Db::rollBack(); | 
				
			|||
            return $e->getMessage(); | 
				
			|||
 | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @inheritDoc | 
				
			|||
     */ | 
				
			|||
    public function addOfflineOrder($data) | 
				
			|||
    { | 
				
			|||
        Db::beginTransaction(); | 
				
			|||
        try { | 
				
			|||
            // 主订单数据
 | 
				
			|||
            $dataMain = []; | 
				
			|||
 | 
				
			|||
            // 获取分布式全局ID
 | 
				
			|||
            $generator = ApplicationContext::getContainer()->get(IdGeneratorInterface::class); | 
				
			|||
            $globalRrderId = $generator->generate(); | 
				
			|||
 | 
				
			|||
            // 主订单插入数据
 | 
				
			|||
            $currentTime = time(); | 
				
			|||
            $dataMain = [ | 
				
			|||
                'delivery_no' => '', | 
				
			|||
                'dada_fee' => 0, | 
				
			|||
                'market_id' => 0, | 
				
			|||
                'box_money' => 0, | 
				
			|||
                'ps_money' => 0, | 
				
			|||
                'mj_money' => 0, | 
				
			|||
                'xyh_money' => 0, | 
				
			|||
                'yhq_money' => 0, | 
				
			|||
                'yhq_money2' => 0, | 
				
			|||
                'zk_money' => 0, | 
				
			|||
                'tel' => '', | 
				
			|||
                'name' => '', | 
				
			|||
                'address' => '', | 
				
			|||
                'area' => '', | 
				
			|||
                'lat' => '', | 
				
			|||
                'lng' => '', | 
				
			|||
                'note' => '', | 
				
			|||
                'form_id' => '', | 
				
			|||
                'form_id2' => '', | 
				
			|||
                'delivery_time' => '', | 
				
			|||
                'order_type' => 0, | 
				
			|||
                'coupon_id' => 0, | 
				
			|||
                'coupon_id2' => 0, | 
				
			|||
                'store_list' => '', | 
				
			|||
                'receive_coupon_ids' => '', | 
				
			|||
                'type' => OrderMain::ORDER_TYPE_OFFLINE, | 
				
			|||
                'time' => date('Y-m-d H:i:s', $currentTime), | 
				
			|||
                'time_add' => $currentTime, | 
				
			|||
                'pay_time' => '', | 
				
			|||
                'pay_type' => OrderMain::ORDER_PAY_WX, | 
				
			|||
                'state' => OrderMain::ORDER_STATE_UNPAY, | 
				
			|||
                'dm_state' => OrderMain::ORDER_STATE_UNPAY, | 
				
			|||
                'code' => $globalRrderId, | 
				
			|||
                'jj_note' => '', | 
				
			|||
                'uniacid' => 2, | 
				
			|||
                'order_num' => 'dm'.date('YmdHis', time()) . rand(1111, 9999), | 
				
			|||
                'money' => $data['money'], | 
				
			|||
                'user_id' => $data['user_id'], | 
				
			|||
                'store_ids' => $data['store_id'], | 
				
			|||
                'global_order_id' => $globalRrderId, | 
				
			|||
            ]; | 
				
			|||
 | 
				
			|||
            // 主订单模型保存
 | 
				
			|||
            $orderMain = OrderMain::create($dataMain); | 
				
			|||
            $orderMainId = $orderMain->id; | 
				
			|||
 | 
				
			|||
            // 子订单模型保存
 | 
				
			|||
            $dataChild = [ | 
				
			|||
                'uniacid' => 1, | 
				
			|||
                'order_num' => 's'.date('YmdHis', time()) . rand(1111, 9999), | 
				
			|||
                'user_id' => $orderMain->user_id, | 
				
			|||
                'store_id' => $data['store_id'], | 
				
			|||
                'order_main_id' => $orderMainId, | 
				
			|||
                'state' => OrderMain::ORDER_STATE_UNPAY, | 
				
			|||
                'dm_state' => OrderMain::ORDER_STATE_UNPAY, | 
				
			|||
                'tel' => $orderMain->tel, | 
				
			|||
                'name' => $orderMain->name, | 
				
			|||
                'address' => $orderMain->address, | 
				
			|||
                'area' => $orderMain->area, | 
				
			|||
                'time' => date("Y-m-d H:i:s"), | 
				
			|||
                'note' => '', | 
				
			|||
                'delivery_time' => $orderMain->delivery_time, | 
				
			|||
                'type' => $orderMain->type, | 
				
			|||
                'lat' => $orderMain->lat, | 
				
			|||
                'lng' => $orderMain->lng, | 
				
			|||
                'pay_type' => $orderMain->pay_type, | 
				
			|||
                'order_type' => $orderMain->order_type, | 
				
			|||
                'money' => $data['money'], | 
				
			|||
                'box_money' => 0, | 
				
			|||
                'mj_money' => 0, | 
				
			|||
                'yhq_money' => 0, | 
				
			|||
                'yhq_money2' => 0, | 
				
			|||
                'zk_money' => 0, | 
				
			|||
                'coupon_id' => 0, | 
				
			|||
                'coupon_id2' => 0, | 
				
			|||
                'xyh_money' => 0, | 
				
			|||
                'time_add' => date("Y-m-d H:i:s"), | 
				
			|||
                'jj_note' => '', | 
				
			|||
                'form_id' => '', | 
				
			|||
                'form_id2' => '', | 
				
			|||
                'code' => '', | 
				
			|||
            ]; | 
				
			|||
 | 
				
			|||
            $orderChildId = Order::query()->insertGetId($dataChild); | 
				
			|||
 | 
				
			|||
            Db::commit(); | 
				
			|||
            return $orderMainId; | 
				
			|||
        } catch (Exception $e) { | 
				
			|||
            Db::rollBack(); | 
				
			|||
            return '购买失败'; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 计算和校验当前订单可用红包及金额 | 
				
			|||
     * @param $couponIds | 
				
			|||
     * @param $orderAmount | 
				
			|||
     * @param $userId | 
				
			|||
     * @param $marketId | 
				
			|||
     * @throws Exception | 
				
			|||
     */ | 
				
			|||
    protected function getCouponAmount($couponIds, $orderAmount, $userId, $marketId) | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        // 用户当前订单可用优惠券
 | 
				
			|||
        $couponsCanUse = $this->couponService->getOrderCanUseCoupons( | 
				
			|||
            $orderAmount, | 
				
			|||
            $marketId, | 
				
			|||
            $userId, | 
				
			|||
            [ | 
				
			|||
                'receive.id', | 
				
			|||
                'receive.user_id', | 
				
			|||
                'receive.number', | 
				
			|||
                'receive.number_remain', | 
				
			|||
                'receive.system_coupon_user_id', | 
				
			|||
                'coupon.discounts', | 
				
			|||
                'coupon.discount_type', | 
				
			|||
            ] | 
				
			|||
        ); | 
				
			|||
 | 
				
			|||
        $couponCanUseIds = array_column($couponsCanUse, 'id'); | 
				
			|||
        $couponCanUseIds = array_intersect($couponCanUseIds, $couponIds); | 
				
			|||
        $couponCannotUseIds = array_diff($couponIds, $couponCanUseIds); | 
				
			|||
 | 
				
			|||
        if (empty($couponCanUseIds)||!empty($couponCannotUseIds)) { | 
				
			|||
            throw new Exception('您的订单中有优惠券已经失效'); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // 计算红包折扣金额
 | 
				
			|||
        $couponMoney = 0; | 
				
			|||
        foreach ($couponsCanUse as $key => $coupon) { | 
				
			|||
 | 
				
			|||
            if (!in_array($coupon->id, $couponIds)) { | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            if ($coupon->discount_type == Coupon::DISCOUNT_TYPE_CASH) { | 
				
			|||
                $couponMoney = bcadd($couponMoney, $coupon->discounts, 2); | 
				
			|||
            } elseif ($coupon->discount_type == Coupon::DISCOUNT_TYPE_RATE) { | 
				
			|||
                $discountRate = bcdiv($coupon->discounts,10); | 
				
			|||
                $discountRate = bcsub(1,$discountRate); | 
				
			|||
                $discountMoney = bcmul($orderAmount, $discountRate); | 
				
			|||
                $couponMoney = bcadd($couponMoney, $discountMoney, 2); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $couponMoney; | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 订单是否存在 | 
				
			|||
     * @param $orderNum | 
				
			|||
     * @return \Hyperf\Utils\HigherOrderTapProxy|mixed|void|null | 
				
			|||
     */ | 
				
			|||
    public function existsByOrderNum($orderNum) | 
				
			|||
    { | 
				
			|||
        return OrderMain::query()->where(['order_num' => $orderNum])->value('id'); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,29 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service; | 
				
			|||
 | 
				
			|||
interface OrderServiceInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * 线上订单下单 | 
				
			|||
     * 外卖 | 
				
			|||
     * @param $data | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function addOnlineOrder($data); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 线下订单下单 | 
				
			|||
     * 扫码支付 | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function addOfflineOrder($data); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 订单是否已经存在 | 
				
			|||
     * @param $orderNum | 
				
			|||
     * @return mixed | 
				
			|||
     */ | 
				
			|||
    public function existsByOrderNum($orderNum); | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,62 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\TaskWorker; | 
				
			|||
 | 
				
			|||
use App\Commons\Log; | 
				
			|||
use Hyperf\Utils\ApplicationContext; | 
				
			|||
use Hyperf\Task\Annotation\Task; | 
				
			|||
use AlibabaCloud\Client\AlibabaCloud; | 
				
			|||
use AlibabaCloud\Client\Exception\ClientException; | 
				
			|||
use AlibabaCloud\Client\Exception\ServerException; | 
				
			|||
use Hyperf\Di\Annotation\Inject; | 
				
			|||
 | 
				
			|||
class AliIotTask | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * @Inject | 
				
			|||
     * @var Log | 
				
			|||
     */ | 
				
			|||
    protected $log; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @var DefaultAcsClient | 
				
			|||
     */ | 
				
			|||
    public $client = null; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Task | 
				
			|||
     */ | 
				
			|||
    public function exec($device_name, $msg) | 
				
			|||
    { | 
				
			|||
        AlibabaCloud::accessKeyClient('LTAI4GJEWrN6dVh7HmPKHMyF', 'wMae4ckfVGwMQPVw5ZlVDDpihVeUap') | 
				
			|||
            ->regionId('cn-shanghai') | 
				
			|||
            ->asDefaultClient(); | 
				
			|||
 | 
				
			|||
        try { | 
				
			|||
            AlibabaCloud::rpc() | 
				
			|||
                ->product('Iot') | 
				
			|||
                ->version('2018-01-20') | 
				
			|||
                ->action('Pub') | 
				
			|||
                ->method('POST') | 
				
			|||
                ->host('iot.cn-shanghai.aliyuncs.com') | 
				
			|||
                ->options([ | 
				
			|||
                    'query' => [ | 
				
			|||
                        'RegionId' => "cn-shanghai", | 
				
			|||
                        'TopicFullName' => "/a1ZSurIJmO0/".$device_name."/user/get", | 
				
			|||
                        'MessageContent' => base64_encode($msg), | 
				
			|||
                        'ProductKey' => "a1ZSurIJmO0", | 
				
			|||
                    ], | 
				
			|||
                ]) | 
				
			|||
                ->request(); | 
				
			|||
        } catch (ClientException $e) { | 
				
			|||
            echo $e->getErrorMessage() . PHP_EOL; | 
				
			|||
        } catch (ServerException $e) { | 
				
			|||
            echo $e->getErrorMessage() . PHP_EOL; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return true; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
@ -0,0 +1,94 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
/** | 
				
			|||
 * This file is part of Hyperf. | 
				
			|||
 * | 
				
			|||
 * @link     https://www.hyperf.io | 
				
			|||
 * @document https://hyperf.wiki | 
				
			|||
 * @contact  group@hyperf.io | 
				
			|||
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE | 
				
			|||
 */ | 
				
			|||
return [ | 
				
			|||
    'default' => 'oss', | 
				
			|||
    'storage' => [ | 
				
			|||
        'local' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\LocalAdapterFactory::class, | 
				
			|||
            'root' => BASE_PATH . '/attachment', | 
				
			|||
        ], | 
				
			|||
        'ftp' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\FtpAdapterFactory::class, | 
				
			|||
            'host' => 'ftp.example.com', | 
				
			|||
            'username' => 'username', | 
				
			|||
            'password' => 'password', | 
				
			|||
            // 'port' => 21,
 | 
				
			|||
            // 'root' => '/path/to/root',
 | 
				
			|||
            // 'passive' => true,
 | 
				
			|||
            // 'ssl' => true,
 | 
				
			|||
            // 'timeout' => 30,
 | 
				
			|||
            // 'ignorePassiveAddress' => false,
 | 
				
			|||
        ], | 
				
			|||
        'memory' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\MemoryAdapterFactory::class, | 
				
			|||
        ], | 
				
			|||
        's3' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\S3AdapterFactory::class, | 
				
			|||
            'credentials' => [ | 
				
			|||
                'key' => env('S3_KEY'), | 
				
			|||
                'secret' => env('S3_SECRET'), | 
				
			|||
            ], | 
				
			|||
            'region' => env('S3_REGION'), | 
				
			|||
            'version' => 'latest', | 
				
			|||
            'bucket_endpoint' => false, | 
				
			|||
            'use_path_style_endpoint' => false, | 
				
			|||
            'endpoint' => env('S3_ENDPOINT'), | 
				
			|||
            'bucket_name' => env('S3_BUCKET'), | 
				
			|||
        ], | 
				
			|||
        'minio' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\S3AdapterFactory::class, | 
				
			|||
            'credentials' => [ | 
				
			|||
                'key' => env('S3_KEY'), | 
				
			|||
                'secret' => env('S3_SECRET'), | 
				
			|||
            ], | 
				
			|||
            'region' => env('S3_REGION'), | 
				
			|||
            'version' => 'latest', | 
				
			|||
            'bucket_endpoint' => false, | 
				
			|||
            'use_path_style_endpoint' => true, | 
				
			|||
            'endpoint' => env('S3_ENDPOINT'), | 
				
			|||
            'bucket_name' => env('S3_BUCKET'), | 
				
			|||
        ], | 
				
			|||
        'oss' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\AliyunOssAdapterFactory::class, | 
				
			|||
            'accessId' => env('OSS_ACCESS_ID'), | 
				
			|||
            'accessSecret' => env('OSS_ACCESS_SECRET'), | 
				
			|||
            'bucket' => env('OSS_BUCKET'), | 
				
			|||
            'endpoint' => env('OSS_ENDPOINT'), | 
				
			|||
            // 'timeout'        => 3600,
 | 
				
			|||
            // 'connectTimeout' => 10,
 | 
				
			|||
            // 'isCName'        => false,
 | 
				
			|||
            // 'token'          => '',
 | 
				
			|||
        ], | 
				
			|||
        'qiniu' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\QiniuAdapterFactory::class, | 
				
			|||
            'accessKey' => env('QINIU_ACCESS_KEY'), | 
				
			|||
            'secretKey' => env('QINIU_SECRET_KEY'), | 
				
			|||
            'bucket' => env('QINIU_BUCKET'), | 
				
			|||
            'domain' => env('QINBIU_DOMAIN'), | 
				
			|||
        ], | 
				
			|||
        'cos' => [ | 
				
			|||
            'driver' => \Hyperf\Filesystem\Adapter\CosAdapterFactory::class, | 
				
			|||
            'region' => env('COS_REGION'), | 
				
			|||
            'credentials' => [ | 
				
			|||
                'appId' => env('COS_APPID'), | 
				
			|||
                'secretId' => env('COS_SECRET_ID'), | 
				
			|||
                'secretKey' => env('COS_SECRET_KEY'), | 
				
			|||
            ], | 
				
			|||
            'bucket' => env('COS_BUCKET'), | 
				
			|||
            'read_from_cdn' => false, | 
				
			|||
            // 'timeout'         => 60,
 | 
				
			|||
            // 'connect_timeout' => 60,
 | 
				
			|||
            // 'cdn'             => '',
 | 
				
			|||
            // 'scheme'          => 'https',
 | 
				
			|||
        ], | 
				
			|||
    ], | 
				
			|||
]; | 
				
			|||
@ -0,0 +1,24 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
declare(strict_types=1); | 
				
			|||
/** | 
				
			|||
 * This file is part of Hyperf. | 
				
			|||
 * | 
				
			|||
 * @link     https://www.hyperf.io | 
				
			|||
 * @document https://hyperf.wiki | 
				
			|||
 * @contact  group@hyperf.io | 
				
			|||
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE | 
				
			|||
 */ | 
				
			|||
use Hyperf\Snowflake\MetaGenerator\RedisMilliSecondMetaGenerator; | 
				
			|||
use Hyperf\Snowflake\MetaGenerator\RedisSecondMetaGenerator; | 
				
			|||
use Hyperf\Snowflake\MetaGeneratorInterface; | 
				
			|||
 | 
				
			|||
return [ | 
				
			|||
    'begin_second' => MetaGeneratorInterface::DEFAULT_BEGIN_SECOND, | 
				
			|||
    RedisMilliSecondMetaGenerator::class => [ | 
				
			|||
        'pool' => 'default', | 
				
			|||
    ], | 
				
			|||
    RedisSecondMetaGenerator::class => [ | 
				
			|||
        'pool' => 'default', | 
				
			|||
    ], | 
				
			|||
]; | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue