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