Browse Source

临时

master
weigang 5 years ago
parent
commit
816fe9eb30
  1. 28
      app/Constants/v3/LogLabel.php
  2. 15
      app/Constants/v3/SsdbKeys.php
  3. 250
      app/Controller/v3/NotifyController.php
  4. 10
      app/Model/v3/CouponRecType.php
  5. 16
      app/Model/v3/SpeakerDevic.php
  6. 530
      app/Service/v3/Implementations/CouponRebateService.php
  7. 139
      app/Service/v3/Implementations/DeviceService.php
  8. 249
      app/Service/v3/Implementations/FeiePrintService.php
  9. 19
      app/Service/v3/Implementations/HelperService.php
  10. 55
      app/Service/v3/Implementations/IOTAliService.php
  11. 212
      app/Service/v3/Implementations/MiniprogramService.php
  12. 81
      app/Service/v3/Implementations/MqttService.php
  13. 78
      app/Service/v3/Implementations/OrderOnlineService.php
  14. 49
      app/Service/v3/Implementations/UserService.php
  15. 24
      app/Service/v3/Interfaces/CouponRebateServiceInterface.php
  16. 12
      app/Service/v3/Interfaces/DeviceServiceInterface.php
  17. 10
      app/Service/v3/Interfaces/FeiePrintServiceInterface.php
  18. 8
      app/Service/v3/Interfaces/IOTServiceInterface.php
  19. 41
      app/Service/v3/Interfaces/MiniprogramServiceInterface.php
  20. 31
      app/Service/v3/Interfaces/MqttServiceInterface.php
  21. 7
      app/Service/v3/Interfaces/OrderOnlineServiceInterface.php
  22. 24
      app/Service/v3/Interfaces/UserServiceInterface.php
  23. 11
      config/autoload/aliiot.php
  24. 9
      config/autoload/award.php
  25. 1
      config/autoload/dependencies.php
  26. 11
      config/autoload/feie.php
  27. 12
      config/autoload/mqtt.php
  28. 14
      config/autoload/wechat.php
  29. 4
      config/routes.php

28
app/Constants/v3/LogLabel.php

@ -13,18 +13,38 @@ use Hyperf\Constants\Annotation\Constants;
class LogLabel extends AbstractConstants class LogLabel extends AbstractConstants
{ {
/** /**
* @Message("Error Code Log")
* @Message("ErrorCode异常抛出")
*/ */
const ERROR_CODE_EXCEPTION = 'error_code_exception';
const ERROR_CODE_EXCEPTION = 'error_code_exception_log';
/** /**
* @Message("Order Online Log")
* @Message("线上订单")
*/ */
const ORDER_ONLINE_LOG = 'order_online_log'; const ORDER_ONLINE_LOG = 'order_online_log';
/** /**
* @Message("Paymetn Log")
* @Message("线下订单")
*/
const ORDER_OFFLINE_LOG = 'order_onffline_log';
/**
* @Message("订单支付")
*/ */
const ORDER_PAYMENT_LOG = 'order_payment_log'; const ORDER_PAYMENT_LOG = 'order_payment_log';
/**
* @Message("IOT设备绑定")
*/
const DEVICE_BIND_LOG = 'device_bind_log';
/**
* @Message("IOT设备Pub消息")
*/
const DEVICE_SEND_LOG = 'device_send_log';
/**
* @Message("优惠券返券")
*/
const COUPON_REBATE_LOG = 'coupon_rebate_log';
} }

15
app/Constants/v3/SsdbKeys.php

@ -60,4 +60,19 @@ class SsdbKeys extends AbstractConstants
*/ */
const ACTIVITY_GOODS_BUY_RECORD = 'activity_goods_buy_record_'; const ACTIVITY_GOODS_BUY_RECORD = 'activity_goods_buy_record_';
/**
* @Message("优惠券返券活动")
*/
const COUPON_REBATE_ACTIVITY = 'coupon_rebate_activity';
/**
* @Message("优惠券返券领券")
*/
const COUPON_REBATE_RECEIVE = 'coupon_rebate_receive_';
/**
* @Message("优惠券返券列表")
*/
const COUPON_REBATE_LIST = 'coupon_rebate_list_';
} }

250
app/Controller/v3/NotifyController.php

@ -0,0 +1,250 @@
<?php
namespace App\Controller\v3;
use App\Constants\v3\LogLabel;
use App\Constants\v3\OrderType;
use App\Controller\BaseController;
use App\Model\v3\OrderMain;
use App\Service\v3\Interfaces\CouponRebateServiceInterface;
use App\Service\v3\Interfaces\DeviceServiceInterface;
use App\Service\v3\Interfaces\FeiePrintServiceInterface;
use App\Service\v3\Interfaces\MiniprogramServiceInterface;
use App\Service\v3\Interfaces\MqttServiceInterface;
use App\Service\v3\Interfaces\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
{
/**
* @Inject
* @var MqttServiceInterface
*/
protected $mqttService;
/**
* @Inject
* @var DeviceServiceInterface
*/
protected $deviceService;
/**
* @Inject
* @var MiniprogramServiceInterface
*/
protected $miniprogramService;
/**
* @Inject
* @var FeiePrintServiceInterface
*/
protected $feiePrintService;
/**
* @Inject
* @var UserServiceInterface
*/
protected $userService;
/**
* @Inject
* @var CouponRebateServiceInterface
*/
protected $couponRebateService;
/**
* @Inject
* @var OrderServiceInterface
*/
protected $orderService;
/**
* @Inject
* @var SeparateAccountsServiceInterface
*/
protected $separateAccountsService;
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();
return $fail('Unknown error but FAIL');
}
// 查询订单
$orderMain = OrderMain::query()
->where([
'global_order_id' => $message['out_trade_no'],
'type' => OrderType::ONLINE
])
->first();
// 订单不存在
if (empty($orderMain) || $orderMain->state == OrderMain::ORDER_STATE_DELIVERY) {
$this->log->event(
LogLabel::PAY_NOTIFY_WXMINI,
['global_order_id_fail' => $message['out_trade_no']]
);
Db::rollBack();
return true;
}
$this->orderService->onlinePaid($message['out_trade_no']);
$this->separateAccountsService->orderOnlinePaid($message['out_trade_no']);
// 优惠券返券
$this->couponRebateService->couponRebateInTask($orderMain->id);
// 喇叭通知,兼容旧音响,MQTT+IOT
$res = $this->mqttService->speakToStore($orderMain->id);
$res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id);
// 公众号模板消息
$res = $this->miniprogramService->sendTemMsgForOnlineOrder($orderMain->id);
// 打印订单,自动打印
$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();
return $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();
return $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;
}
$orderPaid = $this->orderService->offlinePaid($message['out_trade_no']);
$separate = $this->separateAccountsService->orderOfflinePaid($message['out_trade_no']);
// 喇叭通知,兼容旧音响,MQTT+IOT
$res = $this->mqttService->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();
return $fail('Exception');
}
});
return $this->response
->withHeader('Content-Type', 'text/xml')
->withStatus(200)
->withBody(new SwooleStream($response->getContent()));
}
}

10
app/Model/v3/CouponRecType.php

@ -0,0 +1,10 @@
<?php
namespace App\Model\v3;
use App\Model\Model;
class CouponRecType extends Model
{
protected $table = 'lanzu_coupon_receive_type';
}

16
app/Model/v3/SpeakerDevic.php

@ -0,0 +1,16 @@
<?php
namespace App\Model\v3;
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'];
}

530
app/Service/v3/Implementations/CouponRebateService.php

@ -0,0 +1,530 @@
<?php
namespace App\Service\v3\Implementations;
use App\Service\v3\Interfaces\CouponRebateServiceInterface;
use App\Service\v3\Interfaces\HelperServiceInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\DbConnection\Db;
use App\Model\v3\Coupon;
use App\Model\v3\CouponRecType;
use App\Model\v3\CouponRec;
use App\Constants\v3\LogLabel;
use App\Commons\Log;
use Hyperf\Utils\ApplicationContext;
use App\TaskWorker\SSDBTask;
use App\Constants\v3\SsdbKeys;
use Exception;
class CouponRebateService implements CouponRebateServiceInterface
{
/**
* @Inject
* @var Log
*/
protected $log;
/**
* @Inject
* @var HelperServiceInterface
*/
protected $helperService;
/**
* 领取优惠券
* 返券活动领取
* 一次可领取多张优惠券
* 一个用户不可重复领取
*/
public function userReceiveCoupon($params)
{
$userId = $params["user_id"];
$receiveType = $params["receive_type"];
$sendUserId = $params["send_user_id"];
$phone = $params["phone"];
// status: 0领取成功 >0领取失败
$result = [
'status' => 1,
'coupon_text' => '活动已过期~'
];
/* 如果请求的优惠券ids为空,则返回过期提示 */
if($this->helperService->nonempty($params["ids"])){
return $result;
}
$ids = $params["ids"];
$idsData = is_array($ids) ? $ids : explode(',',$ids);
// 错误日志记录
$errorData = [
'coupon_ids' =>$ids,
'user_id' =>$userId,
'receiveType' =>$receiveType,
'sendUserId' =>$sendUserId,
'phone' =>$phone
];
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
$activity = $ssdb->exec('hget', SsdbKeys::COUPON_REBATE_ACTIVITY ,'activity');
// ssdb 键值
$ssdbKey = 'activity_'.$activity.'_user_'.$userId;
$receiveSsdb = [];
// 判断是否已全部领取过
$userReceive = $ssdb->exec('hget', SsdbKeys::COUPON_REBATE_RECEIVE,$ssdbKey);
if($userReceive === false){
$ids = $idsData;
}else{
$userReceiveCouponIds = empty($userReceive) ? [] : explode(',',$userReceive) ;
$ids = array_diff($idsData, $userReceiveCouponIds);
$receiveSsdb = $userReceiveCouponIds;
}
if(count($ids) > 0){
try{
Db::transaction( function() use ($ids,$receiveType,$userId,$sendUserId,$phone,&$result,&$errorData,&$receiveSsdb) {
$now = time();
$success = [];
//获取优惠券信息 (读写锁,完全控制,性能低)
$coupons = Coupon::whereIn('id', $ids)->lockForUpdate()
->where('active_type',2)
->where('status',1)
->where('start_time', '<=', $now)
->where('end_time', '>=', $now)
->whereRaw('inventory > inventory_use')
->select('id','title','inventory','inventory_use','full_amount','discounts','active_type')
->get();
foreach($coupons as $coupon){
$errorData['coupon_id'] = $coupon->id;
// 查询一次能领取的数量
$couponReceiveType = CouponRecType::where('system_coupon_user_id',$coupon->id)->select('one_receive_number');
if (env('SUB_CHANNEL') == 1) {
$couponReceiveType->where('receive_type',$receiveType);
}
$couponReceiveType = $couponReceiveType->first();
// 优惠券可领取数量 >= 本次领取数量
if($coupon->inventory - $coupon->inventory_use >= $couponReceiveType->one_receive_number){
// 判断是否领取过 存在记录则领取过
$isReceive = CouponRec::select('id')
->where('system_coupon_user_id',$coupon->id)
->where('user_id',$userId)
->exists();
if(!$isReceive){
//记录已领取的数量
$coupon->inventory_use += $couponReceiveType->one_receive_number;
$couponReceive = new CouponRec;
$couponReceive->user_id = $userId;
$couponReceive->system_coupon_user_id = $coupon->id;
$couponReceive->order_main_id = 0;
$couponReceive->receive_time = $now;
$couponReceive->number = $couponReceiveType->one_receive_number;
$couponReceive->number_remain = $couponReceiveType->one_receive_number;
$couponReceive->status = 0;
$couponReceive->update_time = $now;
$couponReceive->receive_type = $receiveType;
$couponReceive->send_user_id = $sendUserId;
$couponReceive->phone = $phone;
if ( $couponReceive->save() && $coupon->save() ) {
$success[] = $coupon;
$receiveSsdb[] = $coupon->id;
}else{
$errorData['msg'] = '添加优惠券到用户领取表或者记录已领取数量失败';
$this->log->event(
LogLabel::COUPON_REBATE_LOG,
$errorData
);
}
}
}
}
if(count($success) > 0){
$result['status'] = 0;
$result['coupon_text'] = '恭喜您领取成功!';
}
});
} catch (Exception $e){
$errorData['msg'] = $e->getMessage();
$this->log->event(
LogLabel::COUPON_REBATE_LOG,
$errorData
);
}
if(count($receiveSsdb) > 0){
$saveSsdb = [
$ssdbKey,
implode(',',$receiveSsdb)
];
if(false === $ssdb->exec('hset',SsdbKeys::COUPON_REBATE_RECEIVE, $saveSsdb)){
$errorData['msg'] = '记录领取优惠券到ssdb失败';
$this->log->event(
LogLabel::COUPON_REBATE_LOG,
$errorData
);
};
}
}else{
$result['status'] = 2;
$result['coupon_text'] = '您已领取!赶快去下单吧~';
}
return $result;
}
/*
* 判断用户是否已领取过优惠券
* */
public function isCouponRebate($user_id)
{
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
$activity = $ssdb->exec('hget', SsdbKeys::COUPON_REBATE_ACTIVITY ,'activity');
// ssdb 键值
$ssdbKey = 'activity_'.$activity.'_user_'.$user_id;
// 判断是否已全部领取过
$userReceive = $ssdb->exec('hget', SsdbKeys::COUPON_REBATE_RECEIVE,$ssdbKey);
if($userReceive === false || is_null($userReceive)){
return false;
}else{
return $userReceive;
}
}
/*
*获取活动信息
*/
public function getActiveInfo()
{
//获取SSDB上的活动信息
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
$active = $ssdb->exec('hgetall',SsdbKeys::COUPON_REBATE_ACTIVITY);
$coupon_ids = explode(',',$active['forward']);
$time = time();
$res = Db::table('ims_system_coupon_user')
->whereIn('id',$coupon_ids)
->where([
['status', '=', 1],
['active_type', '=', 2],
['start_time', '<=', $time],
['end_time', '>', $time],
])
->whereRaw('inventory > inventory_use')
->orderBy('weigh', 'desc')
->orderBy('addtime', 'desc')
->get();
return $res;
}
/**
* 将优惠券绑定活动
* 领取优惠券 COUPON_REBATE_FORWARD 可多张
* 返还优惠券 COUPON_REBATE_REPAY 只一张
*/
public function tieCouponActive($couponActivity, $couponForward, $couponRepay)
{
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
$data = [
'activity', $couponActivity,
'forward' , $couponForward,
'repay' , $couponRepay
];
$result = [
'result' => ($ssdb->exec('multi_hset', SsdbKeys::COUPON_REBATE_ACTIVITY, $data) === false) ? false : true ,
'data' => $ssdb->exec('hgetall', SsdbKeys::COUPON_REBATE_ACTIVITY)
];
return $result;
}
/*
* 支付成功 返券
*/
public function couponRebate($order_id)
{
//获取SSDB上的活动信息
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
$active = $ssdb->execWithoutTask('hgetall',SsdbKeys::COUPON_REBATE_ACTIVITY);
//判断返券优惠券是否有库存
$inventory = Db::table('ims_system_coupon_user')
->where('id',$active['repay'])
->whereRaw('inventory > inventory_use')
->exists();
if(!$inventory){
//库存不足
return false;
}
//获取活动发放优惠券id
$coupon_ids = explode(',',$active['forward']);
/* 判断被使用的优惠券类型是否为转发活动优惠券 */
$coupon = Db::table('ims_system_coupon_user_receive as r')
->leftjoin('ims_system_coupon_user_use as u', 'u.user_receive_id', '=', 'r.id')
->where([
['u.order_main_id', '=', $order_id],
['r.send_user_id', '>', 0],
['r.rebate_type', '=', 1],
['r.receive_type', '=', 4],
])
->whereIn('r.system_coupon_user_id',$coupon_ids)
->select('r.user_id', 'r.send_user_id')
->first();
/* 如果使用的优惠券为转发活动优惠券
**则给赠送者返一张优惠券
* **自己给自己转发的券不给返券
*/
if ($coupon && ($coupon->user_id != $coupon->send_user_id)) {
//是否已返过券
$exists_coupon_rebate = Db::table('ims_system_coupon_user_receive')
->where([
['system_coupon_user_id' ,'=', $active['repay']],
['user_id' ,'=', $coupon->send_user_id],
['receive_type' ,'=', 5],
])
->select('id','status')
->first();
//开启事务
Db::beginTransaction();
try {
//返券
if($exists_coupon_rebate){
//如果已有该优惠券 则领取数量 和 可用数量 自增1
Db::table('ims_system_coupon_user_receive')
->where([
['id' ,'=', $exists_coupon_rebate->id],
])
->increment('number');
Db::table('ims_system_coupon_user_receive')
->where([
['id' ,'=', $exists_coupon_rebate->id],
])
->increment('number_remain');
//如果该用户在领取表中 status为已用完状态 2 则改为已用部分 1
if($exists_coupon_rebate->status == 2){
Db::table('ims_system_coupon_user_receive')
->where([
['id' ,'=', $exists_coupon_rebate->id],
])
->update(['status' => 1]);;
}
}else {
//否则新增一条返券记录
$nowTime = time();
Db::table('ims_system_coupon_user_receive')->insert([
[
'user_id' => $coupon->send_user_id,
'system_coupon_user_id' => $active['repay'],
'receive_type' => 5,
'status' => 0,
'number' => 1,
'number_remain' => 1,
'order_main_id' => $order_id,
'receive_time' => $nowTime,
'update_time' => $nowTime,
'created_at' => $nowTime,
'updated_at' => $nowTime,
]
]);
}
//首次返券更新rebate_type字段 防止重复返券
Db::table('ims_system_coupon_user_receive')
->where([
['user_id','=',$coupon->user_id],
['receive_type','=',4],
])
->whereIn('system_coupon_user_id',$coupon_ids)
->update(['rebate_type' => 2]);
//更新库存操作
Db::table('ims_system_coupon_user')
->where('id', $active['repay'])
->increment('inventory_use');
//添加领取记录到ssdb
$data = [
$order_id,$coupon->user_id,
];
$ssdb->execWithoutTask('multi_hset', SsdbKeys::COUPON_REBATE_LIST.$coupon->send_user_id, $data);
// 提交
Db::commit();
} catch (\Exception $e) {
//写入日志文件
$log_Data = array();
$log_Data['name'] = '返券';
$log_Data['order_id'] = $order_id;
$log_Data['msg'] = '返券失败';
$this->log->event(
LogLabel::COUPON_REBATE_LOG,
$log_Data
);
// 回滚
Db::rollBack();
}
}
return true;
}
/*
* 支付成功 返券
*/
public function couponRebateInTask($order_id)
{
//获取SSDB上的活动信息
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
$active = $ssdb->exec('hgetall',SsdbKeys::COUPON_REBATE_ACTIVITY);
//判断返券优惠券是否有库存
$inventory = Db::table('ims_system_coupon_user')
->where('id',$active['repay'])
->whereRaw('inventory > inventory_use')
->exists();
if(!$inventory){
//库存不足
return false;
}
//获取活动发放优惠券id
$coupon_ids = explode(',',$active['forward']);
/* 判断被使用的优惠券类型是否为转发活动优惠券 */
$coupon = Db::table('ims_system_coupon_user_receive as r')
->leftjoin('ims_system_coupon_user_use as u', 'u.user_receive_id', '=', 'r.id')
->where([
['u.order_main_id', '=', $order_id],
['r.send_user_id', '>', 0],
['r.rebate_type', '=', 1],
['r.receive_type', '=', 4],
])
->whereIn('r.system_coupon_user_id',$coupon_ids)
->select('r.user_id', 'r.send_user_id')
->first();
/* 如果使用的优惠券为转发活动优惠券
**则给赠送者返一张优惠券
* **自己给自己转发的券不给返券
*/
if ($coupon && ($coupon->user_id != $coupon->send_user_id)) {
//是否已返过券
$exists_coupon_rebate = Db::table('ims_system_coupon_user_receive')
->where([
['system_coupon_user_id' ,'=', $active['repay']],
['user_id' ,'=', $coupon->send_user_id],
['receive_type' ,'=', 5],
])
->select('id','status')
->first();
//开启事务
Db::beginTransaction();
try {
//返券
if($exists_coupon_rebate){
//如果已有该优惠券 则领取数量 和 可用数量 自增1
Db::table('ims_system_coupon_user_receive')
->where([
['id' ,'=', $exists_coupon_rebate->id],
])
->increment('number');
Db::table('ims_system_coupon_user_receive')
->where([
['id' ,'=', $exists_coupon_rebate->id],
])
->increment('number_remain');
//如果该用户在领取表中 status为已用完状态 2 则改为已用部分 1
if($exists_coupon_rebate->status == 2){
Db::table('ims_system_coupon_user_receive')
->where([
['id' ,'=', $exists_coupon_rebate->id],
])
->update(['status' => 1]);;
}
}else {
//否则新增一条返券记录
$nowTime = time();
Db::table('ims_system_coupon_user_receive')->insert([
[
'user_id' => $coupon->send_user_id,
'system_coupon_user_id' => $active['repay'],
'receive_type' => 5,
'status' => 0,
'number' => 1,
'number_remain' => 1,
'order_main_id' => $order_id,
'receive_time' => $nowTime,
'update_time' => $nowTime,
'created_at' => $nowTime,
'updated_at' => $nowTime,
]
]);
}
//首次返券更新rebate_type字段 防止重复返券
Db::table('ims_system_coupon_user_receive')
->where([
['user_id','=',$coupon->user_id],
['receive_type','=',4],
])
->whereIn('system_coupon_user_id',$coupon_ids)
->update(['rebate_type' => 2]);
//更新库存操作
Db::table('ims_system_coupon_user')
->where('id', $active['repay'])
->increment('inventory_use');
//添加领取记录到ssdb
$data = [
$order_id,$coupon->user_id,
];
$ssdb->exec('multi_hset', SsdbKeys::COUPON_REBATE_LIST.$coupon->send_user_id, $data);
// 提交
Db::commit();
} catch (\Exception $e) {
//写入日志文件
$log_Data = array();
$log_Data['name'] = '返券';
$log_Data['order_id'] = $order_id;
$log_Data['msg'] = '返券失败';
$this->log->event(
LogLabel::COUPON_REBATE_LOG,
$log_Data
);
// 回滚
Db::rollBack();
}
}
return true;
}
/**
* 清优惠券领取记录(SSDB)
*/
public function clearSsdbCouponReceiveByName($activity, $userId, $get = 0, $isAll = 0){
$key = 'activity_'.$activity.'_user_'.$userId;
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
if($isAll > 0){
if($get > 0){
return $ssdb->exec('hgetAll', SsdbKeys::COUPON_REBATE_RECEIVE);
}else{
return ( $ssdb->exec('hclear', SsdbKeys::COUPON_REBATE_RECEIVE) === false) ? false : true ;
}
}else {
if($get > 0){
return $ssdb->exec('hget', SsdbKeys::COUPON_REBATE_RECEIVE, $key);
}else{
return ( $ssdb->exec('hdel', SsdbKeys::COUPON_REBATE_RECEIVE, $key) === false) ? false : true ;
}
}
}
}

139
app/Service/v3/Implementations/DeviceService.php

@ -0,0 +1,139 @@
<?php
namespace App\Service\v3\Implementations;
use App\Commons\Log;
use App\Constants\v3\LogLabel;
use App\Model\v3\Order;
use App\Model\v3\SpeakerDevic;
use App\Model\v3\Store;
use App\Service\v3\Interfaces\DeviceServiceInterface;
use App\Service\v3\Interfaces\IOTServiceInterface;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Collection;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\ApplicationContext;
use Throwable;
class DeviceService implements DeviceServiceInterface
{
/**
* @Inject
* @var Log
*/
protected $log;
/**
* @Inject
* @var IOTServiceInterface
*/
protected $IOTService;
/**
* 获取绑定列表
* @param $store_id
* @return Builder[]|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_BIND_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 = $order['type']==1 ? "{\"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();
}
}

249
app/Service/v3/Implementations/FeiePrintService.php

@ -0,0 +1,249 @@
<?php
namespace App\Service\v3\Implementations;
use App\Libs\FeiePrintClient;
use App\Service\v3\Interfaces\FeiePrintServiceInterface;
use Hyperf\DbConnection\Db;
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/';
protected $feieUser = '';
protected $feieUkey = '';
protected $feieHost = '';
protected $feiePort = '';
protected $feieApiPath = '';
public function __construct()
{
$this->feieUser = config('feie.user');
$this->feieUkey = config('feie.ukey');
$this->feieHost = config('feie.host');
$this->feiePort = config('feie.port');
$this->feieApiPath = config('feie.api_path');
}
public function feiePrint($order_num)
{
// TODO 对象数组=》二维数组
$data = Db::table('lanzu_order_main as m')
->join('lanzu_order as o','o.order_main_id', '=', 'm.id','inner')
->join('lanzu_order_goods as g','o.id','=', 'g.order_id','inner')
->join('lanzu_feprint as f','m.market_id','=', 'f.market_id','inner')
->join('lanzu_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();
if (empty($data)) {
return ;
}
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' => $this->feieUser,
'stime' => $time,
'sig' => sha1($this->feieUser . $this->feieUkey . $time),
'apiname' => 'Open_printMsg',
'sn' => $sn,
'content' => $content,
'times' => $times//打印次数
);
$client = new FeiePrintClient($this->feieHost, $this->feiePort);
if (!$client->post($this->feieApiPath, $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;
}
}

19
app/Service/v3/Implementations/HelperService.php

@ -17,4 +17,23 @@ class HelperService implements HelperServiceInterface
// 返回验证码 // 返回验证码
return implode('', $codeArr); return implode('', $codeArr);
} }
/**
* 请求参数判空
* @param mixed $var 参数
* @return bool
*/
public function nonempty($var)
{
return ! (
isset($var)
&& $var
&& !empty($var)
&& !is_null($var)
&& $var != 'undefined'
&& $var != 'unknown'
&& $var != 'null'
&& $var != 'false'
);
}
} }

55
app/Service/v3/Implementations/IOTAliService.php

@ -0,0 +1,55 @@
<?php
namespace App\Service\v3\Implementations;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use App\Commons\Log;
use App\Constants\v3\LogLabel;
use App\Service\v3\Interfaces\IOTServiceInterface;
use Hyperf\Di\Annotation\Inject;
class IOTAliService implements IOTServiceInterface
{
/**
* @Inject
* @var Log
*/
protected $log;
public function pub($device_name, $msg)
{
AlibabaCloud::accessKeyClient(config('aliiot.key'), config('aliiot.secret'))
->regionId(config('aliiot.region'))
->asDefaultClient();
try {
AlibabaCloud::rpc()
->product('Iot')
->version('2018-01-20')
->action('Pub')
->method('POST')
->host(config('aliiot.host'))
->options([
'query' => [
'RegionId' => "cn-shanghai",
'TopicFullName' => "/".config('aliiot.prod_key')."/".$device_name."/user/get",
'MessageContent' => base64_encode($msg),
'ProductKey' => config('aliiot.prod_key'),
],
])
->request();
} catch (ClientException $e) {
$this->log->event(LogLabel::DEVICE_SEND_LOG, ['msg' => 'ClientException发布失败:'.$e->getErrorMessage()]);
return false;
} catch (ServerException $e) {
$this->log->event(LogLabel::DEVICE_SEND_LOG, ['msg' => 'ServerException发布失败:'.$e->getErrorMessage()]);
return false;
}
return true;
}
}

212
app/Service/v3/Implementations/MiniprogramService.php

@ -0,0 +1,212 @@
<?php
namespace App\Service\v3\Implementations;
use App\Model\v3\Order;
use App\Model\v3\OrderGoods;
use App\Model\v3\OrderMain;
use App\Model\v3\Store;
use App\Model\v3\User;
use App\Service\v3\Interfaces\MiniprogramServiceInterface;
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'] = User::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 = User::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'] = User::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' => ''])
{
if (empty($openid) || empty($template_id) || empty($data)) {
return ;
}
// 先拼个基础的
$template = [
'touser' => $openid,
'mp_template_msg' => [
'appid' => config('wechat.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('wechat.applet'));
$app['guzzle_handler'] = CoroutineHandler::class;
$app->uniform_message->send($template);
}
}

81
app/Service/v3/Implementations/MqttService.php

@ -0,0 +1,81 @@
<?php
namespace App\Service\v3\Implementations;
use App\Constants\v3\OrderType;
use App\Libs\MQTTClient;
use App\Model\v3\Order;
use App\Model\v3\Store;
use Hyperf\Utils\ApplicationContext;
use App\Service\v3\Interfaces\MqttServiceInterface;
class MqttService implements MqttServiceInterface
{
/**
* @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'] = $order['type']==OrderType::ONLINE ? "您有新的懒族外卖订单" : "微信到账".floatval($order['money'])."";
// 获取终端ID
$order['to_client_id'] = Store::query()->where(['id' => $order['store_id']])->value('loudspeaker_imei');
// 发布订阅消息
$res = $this->publish($order['template'], config('mqtt.topic'), $order['to_client_id']);
}
}
/**
* @inheritDoc
*/
public function publish(
$message,
$topic,
$toClientId = '',
$type = '',
$payId = '',
$curClientId = ''
) {
$client = new MQTTClient(config('mqtt.host'), config('mqtt.port'));
$client->setAuthentication(config('mqtt.name'), config('mqtt.pass'));
$client->setDebug(true);
if (config('mqtt.cert')) {
$client->setEncryption(config('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();
}
}

78
app/Service/v3/Implementations/OrderOnlineService.php

@ -391,4 +391,82 @@ class OrderOnlineService implements OrderOnlineServiceInterface
return ['order_main' => $orderMain, 'orders' => $orders]; return ['order_main' => $orderMain, 'orders' => $orders];
} }
/**
* @inheritDoc
*/
public function doByPaid($orderMainId)
{
Db::beginTransaction();
try {
// 查询订单
$orderMain = OrderMain::query()
->where(['id' => $orderMainId,'type' => OrderType::ONLINE])
->first();
// 修改订单、子订单状态
$currentTime = time();
$orderMain->state = OrderState::PAID;
$orderMain->time_pay = $currentTime;
$orderMain->pay_time = date('Y-m-d H:i:s', $currentTime);
$orderMain->save();;
// 更新商户销量
$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'])
->where(['order_main_id' => $orderMain->id])
->get()
->toArray();
$orderGoods = OrderGoods::query()->select(['good_id AS id', 'number', 'combination_id'])
->whereIn('order_id', array_values(array_column($orders, 'id')))
->get()
->toArray();
foreach ($orderGoods as $key => &$goodsItem) {
$goods = Goods::find($goodsItem['id']);
// 库存处理,有规格
if ($goodsItem['combination_id']) {
$combination = SpecCombination::find($goodsItem['combination_id']);
$combination->number = $combination->number - $goodsItem['number'];
$combination->save();
} else {
$goods->inventory = $goods->inventory - $goodsItem['number'];
}
$goods->sales = $goods->sales - $goodsItem['number'];
$goods->save();
}
// 月销流水
$statistics = [];
foreach ($orders as $key => &$order) {
$statistics[] = [
'money' => $order['money'],
'user_id' => $order['user_id'],
'store_id' => $order['store_id'],
'market_id' => $orderMain->market_id,
'order_id' => $order['id'],
'createtime' => strtotime($order['pay_time']),
];
}
if (is_array($statistics) && !empty($statistics)) {
$inSalesStatistics = OrderSalesStatistic::query()->insert($statistics);
}
Db::commit();
return true;
} catch (Exception $e) {
$this->log->event(LogLabel::ONLINE_PAID_LOG, ['exception' => $e->getMessage()]);
Db::rollBack();
return false;
}
}
} }

49
app/Service/v3/Implementations/UserService.php

@ -0,0 +1,49 @@
<?php
namespace App\Service\v3\Implementations;
use App\Constants\v3\OrderState;
use App\Constants\v3\OrderType;
use App\Model\v3\Order;
use App\Model\v3\OrderMain;
use App\Service\v3\Interfaces\UserServiceInterface;
class UserService implements UserServiceInterface
{
/**
* 是否平台新用户
* 在很多奖励的地方会需要用到这个查询
* 判定条件:
* 没有在平台下过单(包括线上和线下)
* @param $user_id
* @param $order_main_id
* @return mixed|void
*/
public function isPlatformNewUser($user_id, $order_main_id): bool
{
return !OrderMain::query()
->where(['user_id' => $user_id])
->where('id', '!=', $order_main_id)
->where(function ($query){
$query->whereIn('state', OrderState::FINISH);
})
->exists();
}
/**
* @inheritDoc
*/
public function isStoreFirstOrderToday($user_id, $store_id, $current_order_id, $limit_amount = 3)
{
return !Order::query()
->where(['user_id' => $user_id, 'store_id' => $store_id, 'type' => OrderType::OFFLINE])
->whereIn('state', OrderState::FINISH)
->where('time_add', '>=', date('Y-m-d 00:00:00'))
->where('time_add', '<=', date('Y-m-d 23:59:59'))
->where('money', '>=', $limit_amount)
->where('id', '!=', $current_order_id)
->exists();
}
}

24
app/Service/v3/Interfaces/CouponRebateServiceInterface.php

@ -0,0 +1,24 @@
<?php
namespace App\Service\v3\Interfaces;
interface CouponRebateServiceInterface
{
/**
* 领取优惠券
*/
public function userReceiveCoupon($params);
public function isCouponRebate($user_id);
public function getActiveInfo();
public function tieCouponActive($couponActivity,$couponForward,$couponRepay);
public function couponRebate($order_id);
public function couponRebateInTask($order_id);
public function clearSsdbCouponReceiveByName($activity, $userId, $get = 0, $isAll = 0);
}

12
app/Service/v3/Interfaces/DeviceServiceInterface.php

@ -0,0 +1,12 @@
<?php
namespace App\Service\v3\Interfaces;
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);
}

10
app/Service/v3/Interfaces/FeiePrintServiceInterface.php

@ -0,0 +1,10 @@
<?php
namespace App\Service\v3\Interfaces;
interface FeiePrintServiceInterface
{
public function feiePrint($order_num);
}

8
app/Service/v3/Interfaces/IOTServiceInterface.php

@ -0,0 +1,8 @@
<?php
namespace App\Service\v3\Interfaces;
interface IOTServiceInterface
{
public function pub($device_name, $msg);
}

41
app/Service/v3/Interfaces/MiniprogramServiceInterface.php

@ -0,0 +1,41 @@
<?php
namespace App\Service\v3\Interfaces;
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' => '']);
}

31
app/Service/v3/Interfaces/MqttServiceInterface.php

@ -0,0 +1,31 @@
<?php
namespace App\Service\v3\Interfaces;
interface MqttServiceInterface
{
/**
* 发布给商户
* @param $orderId
* @param bool $isMain
* @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 = ''
);
}

7
app/Service/v3/Interfaces/OrderOnlineServiceInterface.php

@ -11,4 +11,11 @@ interface OrderOnlineServiceInterface
public function undo(); public function undo();
public function detailByUser($orderMainId, $userId); public function detailByUser($orderMainId, $userId);
/**
* 线上订单支付完成(支付成功)
* @param $orderMainId
* @return mixed
*/
public function doByPaid($orderMainId);
} }

24
app/Service/v3/Interfaces/UserServiceInterface.php

@ -0,0 +1,24 @@
<?php
namespace App\Service\v3\Interfaces;
interface UserServiceInterface
{
/**
* 是否平台新用户
* @param $user_id
* @param $order_main_id
* @return mixed
*/
public function isPlatformNewUser($user_id, $order_main_id): bool;
/**
* 是否店铺当日首单
* @param $user_id
* @param $store_id
* @param $current_order_id
* @param int $limit_amount
* @return mixed
*/
public function isStoreFirstOrderToday($user_id, $store_id, $current_order_id, $limit_amount = 3);
}

11
config/autoload/aliiot.php

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
return [
'host' => env('ALI_IOT_HOST', ''),
'key' => env('ALI_IOT_KEY', ''),
'secret' => env('ALI_IOT_SECRET', ''),
'region' => env('ALI_IOT_REGION', ''),
'prod_key' => env('ALI_IOT_PRODUCT_KEY', ''),
];

9
config/autoload/award.php

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
return [
'limit' => [
'store_new_user' => env('LIMIT_STORE_NEW_USER', 3)
]
];

1
config/autoload/dependencies.php

@ -69,4 +69,5 @@ return [
\App\Service\v3\Interfaces\OrderOfflineServiceInterface::class => \App\Service\v3\Implementations\OrderOfflineService::class, \App\Service\v3\Interfaces\OrderOfflineServiceInterface::class => \App\Service\v3\Implementations\OrderOfflineService::class,
\App\Service\v3\Interfaces\BusinessHoursServiceInterface::class => \App\Service\v3\Implementations\BusinessHoursService::class, \App\Service\v3\Interfaces\BusinessHoursServiceInterface::class => \App\Service\v3\Implementations\BusinessHoursService::class,
\App\Service\v3\Interfaces\UserAddressServiceInterface::class => \App\Service\v3\Implementations\UserAddressService::class, \App\Service\v3\Interfaces\UserAddressServiceInterface::class => \App\Service\v3\Implementations\UserAddressService::class,
\App\Service\v3\Interfaces\MqttServiceInterface::class => \App\Service\v3\Implementations\MqttService::class,
]; ];

11
config/autoload/feie.php

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
return [
'user' => env('FEIE_USER', ''),
'ukey' => env('FEIE_UKEY', ''),
'host' => env('FEIE_API_PATH', ''),
'port' => env('FEIE_PORT', ''),
'api_path' => env('FEIE_API_PATH', ''),
];

12
config/autoload/mqtt.php

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
return [
'host' => env('MQTT_HOST', ''),
'port' => env('MQTT_PORT', ''),
'name' => env('MQTT_NAME', ''),
'pass' => env('MQTT_PASS', ''),
'cert' => env('MQTT_CERT', ''),
'topic' => env('MQTT_TOPIC', ''),
];

14
config/autoload/wechat.php

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
return [
'official' => [
'app_id' => env('OFFICIAL_APP_ID', ''),
'app_secret' => env('OFFICIAL_APP_SECRET', ''),
],
'applet' => [
'app_id' => env('APP_ID',''),
'secret' => env('APP_SECRET',''),
],
];

4
config/routes.php

@ -70,8 +70,8 @@ Router::addGroup('/v1/',function (){
},['middleware' => [\App\Middleware\Auth\ApiMiddleware::class]]); },['middleware' => [\App\Middleware\Auth\ApiMiddleware::class]]);
Router::addGroup('/wechat/',function () { Router::addGroup('/wechat/',function () {
Router::post('notify/wxminionline', 'App\Controller\NotifyController@wxminiOnline');
Router::post('notify/wxminioffline', 'App\Controller\NotifyController@wxminiOffline');
Router::post('notify/wxminionline', 'App\Controller\v3\NotifyController@wxminiOnline');
Router::post('notify/wxminioffline', 'App\Controller\v3\NotifyController@wxminiOffline');
Router::post('notify/wxpayrefund', 'App\Controller\NotifyPayRefundController@wxPayRefund'); Router::post('notify/wxpayrefund', 'App\Controller\NotifyPayRefundController@wxPayRefund');
}); });

Loading…
Cancel
Save