diff --git a/app/Constants/v3/LogLabel.php b/app/Constants/v3/LogLabel.php
index 7d5d55c..e567de8 100644
--- a/app/Constants/v3/LogLabel.php
+++ b/app/Constants/v3/LogLabel.php
@@ -13,18 +13,38 @@ use Hyperf\Constants\Annotation\Constants;
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';
/**
- * @Message("Paymetn Log")
+ * @Message("线下订单")
+ */
+ const ORDER_OFFLINE_LOG = 'order_onffline_log';
+
+ /**
+ * @Message("订单支付")
*/
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';
+
}
diff --git a/app/Constants/v3/SsdbKeys.php b/app/Constants/v3/SsdbKeys.php
index 6937a5b..c2b85bd 100644
--- a/app/Constants/v3/SsdbKeys.php
+++ b/app/Constants/v3/SsdbKeys.php
@@ -60,4 +60,19 @@ class SsdbKeys extends AbstractConstants
*/
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_';
+
}
\ No newline at end of file
diff --git a/app/Controller/v3/NotifyController.php b/app/Controller/v3/NotifyController.php
new file mode 100644
index 0000000..e4a148f
--- /dev/null
+++ b/app/Controller/v3/NotifyController.php
@@ -0,0 +1,250 @@
+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()));
+ }
+}
\ No newline at end of file
diff --git a/app/Model/v3/CouponRecType.php b/app/Model/v3/CouponRecType.php
new file mode 100644
index 0000000..0520617
--- /dev/null
+++ b/app/Model/v3/CouponRecType.php
@@ -0,0 +1,10 @@
+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 ;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/DeviceService.php b/app/Service/v3/Implementations/DeviceService.php
new file mode 100644
index 0000000..cf4f610
--- /dev/null
+++ b/app/Service/v3/Implementations/DeviceService.php
@@ -0,0 +1,139 @@
+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();
+ }
+
+}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/FeiePrintService.php b/app/Service/v3/Implementations/FeiePrintService.php
new file mode 100644
index 0000000..8afde34
--- /dev/null
+++ b/app/Service/v3/Implementations/FeiePrintService.php
@@ -0,0 +1,249 @@
+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 = '懒族生活
';
+ $orderInfo .= '名称 单价 数量 金额
';
+ $orderInfo .= '--------------------------------
';
+ $shopname = "";
+ $shopnum = 0;
+ foreach ($arr as $k5 => $v5) {
+ if ($shopname != $v5['shopname']) {
+ if ($shopname != "") {
+ $orderInfo .= '
';
+ }
+ $shopnum++;
+ $orderInfo .= "(" . $shopnum . ")" .$v5['shopname'] . '
';
+ $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.'
';
+ }
+ 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.'
';
+ }
+ }
+ $orderInfo .= $head.$tail;
+ if(!empty($v5['o_note'])){
+ $orderInfo .= '备注:'.$v5['o_note'].'
';
+ }
+ }
+ // $time = date('Y-m-d H:i:s', time());
+ $orderInfo .= '--------------------------------
';
+ 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'] . '
';
+ }
+ 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'].'
';
+ }
+ 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.'
';
+ }
+ $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.'
';
+ $orderInfo .= '送货地点:' . $arr[0]['address'] . '
';
+ $tel = substr_replace( $arr[0]['tel'], '****', 3, 4);
+ $orderInfo .= '联系电话:' . $tel . '
';
+ $orderInfo .= '配送时间:' . $arr[0]['ps_time'] . '
';
+ if(!empty($arr[0]['note'])){
+ $orderInfo .= '备注:'.$arr[0]['note'].'
';
+ }
+ //$orderInfo .= 'http://www.feieyun.com';//把解析后的二维码生成的字符串用标签套上即可自动生成二维码
+ return $orderInfo;
+ }
+}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/HelperService.php b/app/Service/v3/Implementations/HelperService.php
index 22766a6..1b8e5db 100644
--- a/app/Service/v3/Implementations/HelperService.php
+++ b/app/Service/v3/Implementations/HelperService.php
@@ -17,4 +17,23 @@ class HelperService implements HelperServiceInterface
// 返回验证码
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'
+ );
+ }
}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/IOTAliService.php b/app/Service/v3/Implementations/IOTAliService.php
new file mode 100644
index 0000000..0c10a48
--- /dev/null
+++ b/app/Service/v3/Implementations/IOTAliService.php
@@ -0,0 +1,55 @@
+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;
+ }
+
+}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/MiniprogramService.php b/app/Service/v3/Implementations/MiniprogramService.php
new file mode 100644
index 0000000..124b4cc
--- /dev/null
+++ b/app/Service/v3/Implementations/MiniprogramService.php
@@ -0,0 +1,212 @@
+ '微信支付', '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);
+ }
+
+}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/MqttService.php b/app/Service/v3/Implementations/MqttService.php
new file mode 100644
index 0000000..3ab4873
--- /dev/null
+++ b/app/Service/v3/Implementations/MqttService.php
@@ -0,0 +1,81 @@
+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();
+ }
+}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/OrderOnlineService.php b/app/Service/v3/Implementations/OrderOnlineService.php
index 3e36ea5..20b0ec4 100644
--- a/app/Service/v3/Implementations/OrderOnlineService.php
+++ b/app/Service/v3/Implementations/OrderOnlineService.php
@@ -391,4 +391,82 @@ class OrderOnlineService implements OrderOnlineServiceInterface
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;
+ }
+ }
}
\ No newline at end of file
diff --git a/app/Service/v3/Implementations/UserService.php b/app/Service/v3/Implementations/UserService.php
new file mode 100644
index 0000000..32c64f8
--- /dev/null
+++ b/app/Service/v3/Implementations/UserService.php
@@ -0,0 +1,49 @@
+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();
+ }
+
+}
\ No newline at end of file
diff --git a/app/Service/v3/Interfaces/CouponRebateServiceInterface.php b/app/Service/v3/Interfaces/CouponRebateServiceInterface.php
new file mode 100644
index 0000000..84e2882
--- /dev/null
+++ b/app/Service/v3/Interfaces/CouponRebateServiceInterface.php
@@ -0,0 +1,24 @@
+ '', 'pagepath' => '']);
+}
\ No newline at end of file
diff --git a/app/Service/v3/Interfaces/MqttServiceInterface.php b/app/Service/v3/Interfaces/MqttServiceInterface.php
new file mode 100644
index 0000000..b9423bf
--- /dev/null
+++ b/app/Service/v3/Interfaces/MqttServiceInterface.php
@@ -0,0 +1,31 @@
+ 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', ''),
+];
\ No newline at end of file
diff --git a/config/autoload/award.php b/config/autoload/award.php
new file mode 100644
index 0000000..e75cc62
--- /dev/null
+++ b/config/autoload/award.php
@@ -0,0 +1,9 @@
+ [
+ 'store_new_user' => env('LIMIT_STORE_NEW_USER', 3)
+ ]
+];
\ No newline at end of file
diff --git a/config/autoload/dependencies.php b/config/autoload/dependencies.php
index 679f49b..8f742b5 100644
--- a/config/autoload/dependencies.php
+++ b/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\BusinessHoursServiceInterface::class => \App\Service\v3\Implementations\BusinessHoursService::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,
];
diff --git a/config/autoload/feie.php b/config/autoload/feie.php
new file mode 100644
index 0000000..44c39b9
--- /dev/null
+++ b/config/autoload/feie.php
@@ -0,0 +1,11 @@
+ env('FEIE_USER', ''),
+ 'ukey' => env('FEIE_UKEY', ''),
+ 'host' => env('FEIE_API_PATH', ''),
+ 'port' => env('FEIE_PORT', ''),
+ 'api_path' => env('FEIE_API_PATH', ''),
+];
\ No newline at end of file
diff --git a/config/autoload/mqtt.php b/config/autoload/mqtt.php
new file mode 100644
index 0000000..98cad69
--- /dev/null
+++ b/config/autoload/mqtt.php
@@ -0,0 +1,12 @@
+ env('MQTT_HOST', ''),
+ 'port' => env('MQTT_PORT', ''),
+ 'name' => env('MQTT_NAME', ''),
+ 'pass' => env('MQTT_PASS', ''),
+ 'cert' => env('MQTT_CERT', ''),
+ 'topic' => env('MQTT_TOPIC', ''),
+];
\ No newline at end of file
diff --git a/config/autoload/wechat.php b/config/autoload/wechat.php
new file mode 100644
index 0000000..8739460
--- /dev/null
+++ b/config/autoload/wechat.php
@@ -0,0 +1,14 @@
+ [
+ 'app_id' => env('OFFICIAL_APP_ID', ''),
+ 'app_secret' => env('OFFICIAL_APP_SECRET', ''),
+ ],
+ 'applet' => [
+ 'app_id' => env('APP_ID',''),
+ 'secret' => env('APP_SECRET',''),
+ ],
+];
\ No newline at end of file
diff --git a/config/routes.php b/config/routes.php
index cd0407b..89dca29 100644
--- a/config/routes.php
+++ b/config/routes.php
@@ -70,8 +70,8 @@ Router::addGroup('/v1/',function (){
},['middleware' => [\App\Middleware\Auth\ApiMiddleware::class]]);
Router::addGroup('/wechat/',function () {
- Router::post('notify/wxminionline', 'App\Controller\NotifyController@wxminiOnline');
- Router::post('notify/wxminioffline', 'App\Controller\NotifyController@wxminiOffline');
+ Router::post('notify/wxminionline', 'App\Controller\v3\NotifyController@wxminiOnline');
+ Router::post('notify/wxminioffline', 'App\Controller\v3\NotifyController@wxminiOffline');
Router::post('notify/wxpayrefund', 'App\Controller\NotifyPayRefundController@wxPayRefund');
});