初始化项目

This commit is contained in:
2026-09-01 22:15:50 +08:00
commit b5a26a8848
11217 changed files with 1710987 additions and 0 deletions
@@ -0,0 +1,346 @@
<?php
namespace app\console\command;
use app\common\service\QueueService;
use app\console\model\OrderGoods;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\store\model\order\Record as RecordModel;
use app\common\service\SybOil;
use think\facade\Db;
class CallbackQueue extends Command
{
protected $queueService;
protected function configure()
{
$this->setName('callback:queue')
->setDescription('Process messages from the Redis queue');
}
protected function execute(Input $input, Output $output)
{
$this->queueService = new QueueService();
while (true) {
$message = $this->queueService->pop('callback_queue');
if ($message) {
// 处理消息
$this->processMessage($message);
} else {
// 暂停一段时间再检查队列
sleep(1);
}
}
}
// protected function processMessage($message)
// {
// $SybOil = new SybOil();
// $SybOil->saveLogStore('callback_queue队列数据处理:【'.$message.'】');
// // 拿到队列数据处理
// $data = json_decode($message, true);
// // 检查解码是否成功
// if ($data === false) {
// $SybOil->saveLogStore('callback_queue队列数据解码失败:' . json_last_error_msg());
// return;
// }
// // 确保 $data 中包含 header 和 res
// if (!isset($data['header']) || !isset($data['res'])) {
// $SybOil->saveLogStore('数据格式不正确:【' . $message . '】');
// return;
// }
// $headers = $data['header'];
// $res = $data['res'];
// // 此处可以根据业务逻辑处理接收到的数据
// try {
// switch ($headers['method']) {
// case "syb.notify.pay.result":
// // 二维码交易结果通知
// if($res['oilCardType'] == 'card') {
// $where = array(
// ['oilCardNo', '=', $res['oilCardNo']],
// ['goods_price', '=', $res['amount']],
// );
// }else{
// $where = array(
// ['shareNo', '=', $res['shareNo']],
// ['goods_price', '=', $res['amount']],
// );
// }
// $orderGoods = Db::name('order_goods')
// ->where($where)
// ->find();
// if($orderGoods['order_goods_id']) {
// $field['qrCode'] = $res['qrCode'];
// if ($res['status'] == 'success') {
// $field['use_status'] = 1;
// } else {
// $field['use_text'] = $res['errMessage'];
// }
// // 更新用户使用状态
// Db::name('order_goods')
// ->where('order_goods_id', $orderGoods['order_goods_id'])
// ->update($field);
// }else{
// $SybOil->saveLogStore('未找到订单信息:【'.$message.'】');
// }
// break;
// case "syb.notify.oilCard.change":
// // 油卡变动通知
// $where = array(
// ['oilCardNo', '=', $res['oilCardNo']],
// ['goods_price', '=', $res['amount']],
// );
// $orderGoods = Db::name('order_goods')
// ->where($where)
// ->find();
// $res['order_id'] = $orderGoods['order_id'];
// $res['order_goods_id'] = $orderGoods['order_goods_id'];
// $res['user_id'] = $orderGoods['user_id'];
// $res['store_id'] = $orderGoods['store_id'];
// $RecordModel = new RecordModel();
// // 油卡变动记录写入结果
// $RecordModel->add($res);
// // 更新油券使用状态
// if($orderGoods['order_goods_id'] && $res['optType'] == 'add_oil'){
// Db::name('order_goods')
// ->where('order_goods_id', $orderGoods['order_goods_id'])
// ->update(array(
// 'use_status' => 1,
// 'use_time' => time(),
// 'use_text' => '加油',
// ));
// // 修改主订单为已完成
// Db::name('order')
// ->where('order_id', $orderGoods['order_id'])
// ->update(array(
// 'order_status' => 30
// ));
// // 更新用户使用状态
// Db::name('account')
// ->where('account_id', $orderGoods['account_id'])
// ->update(['last_called_at' => time(), 'state' => 0]);
// $SybOil->saveLogStore('加油回调处理成功了:'.json_encode($res));
// }else{
// $SybOil->saveLogStore('没有处理结果:【'.$message.'】');
// }
// break;
// case "syb.notify.oilCard.share":
// // 分油结果通知
// if($res['oilCardType'] == 'card') {
// $where = array(
// ['oilCardNo', '=', $res['oilCardNo']],
// ['goods_price', '=', $res['amount']],
// );
// }else{
// $where = array(
// ['shareNo', '=', $res['shareNo']],
// ['goods_price', '=', $res['amount']],
// );
// }
// $orderGoods = Db::name('order_goods')
// ->where($where)
// ->find();
// if($orderGoods['order_goods_id']) {
// $field = ['oil_time' => time()];
// if ($res['status'] == 'success') {
// $field['oil_status'] = 1;
// } else {
// $field['oil_status'] = 0;
// $field['oil_text'] = $res['msg'];
// }
// Db::name('order_goods')
// ->where('order_goods_id', $orderGoods['order_goods_id'])
// ->update($field);
//
// $SybOil->saveLogStore('分油回调处理成功了:'.json_encode($res));
// }else{
// $this->queueService->push('callback_queue', json_encode(['header'=>$headers,'res'=>$res],320));
// $SybOil->saveLogStore('重新加入队列:【'.$message.'】');
// }
// break;
// default:
// $SybOil->saveLogStore('队列数据处理异常,未知:【'.$message.'】');
// }
// } catch (\Exception $e) {
// $SybOil->saveLogStore(
// '队列回调处理异常:' . $e->getMessage() .
// ' 在文件:' . $e->getFile() .
// ' 第:' . $e->getLine() .
// ' 行。堆栈跟踪:' . $e->getTraceAsString()
// );
//
// }
// }
protected function processMessage($message)
{
$SybOil = new SybOil();
$SybOil->saveLogStore('callback_queue队列数据处理:【'.$message.'】');
// 拿到队列数据处理
$data = json_decode($message, true);
// 检查解码是否成功
if ($data === false) {
$SybOil->saveLogStore('callback_queue队列数据解码失败:' . json_last_error_msg());
return;
}
// 确保 $data 中包含 header 和 res
if (!isset($data['header']) || !isset($data['res'])) {
$SybOil->saveLogStore('数据格式不正确:【' . $message . '】');
return;
}
$headers = $data['header'];
$res = $data['res'];
// 此处可以根据业务逻辑处理接收到的数据
try {
switch ($headers['method']) {
case "use":
// 油卡变动通知
$where = array(
['shareNo', '=', $res['trade_no']],
);
$orderGoods = Db::name('order_goods')
->where($where)
->find();
$res['order_id'] = $orderGoods['order_id'];
$res['order_goods_id'] = $orderGoods['order_goods_id'];
$res['user_id'] = $orderGoods['user_id'];
$res['store_id'] = $orderGoods['store_id'];
$res['optType'] = 'add_oil';
$RecordModel = new RecordModel();
// 油卡变动记录写入结果
$RecordModel->add($res);
// 更新油券使用状态
if($orderGoods['order_goods_id'] && $res['useStatus'] == '2'){
Db::name('order_goods')
->where('order_goods_id', $orderGoods['order_goods_id'])
->update(array(
'use_status' => 1,
'use_time' => time(),
'use_text' => '加油',
));
// 订单下的券都已使用
if(Db::name('order_goods')->where([['order_id' , '=', $orderGoods['order_id']], ['use_status', '=', '0']])->count() == 0) {
// 修改主订单为已完成
Db::name('order')
->where('order_id', $orderGoods['order_id'])
->update(array(
'order_status' => 30
));
}
// 更新用户使用状态
Db::name('account')
->where('account_id', $orderGoods['account_id'])
->update(['last_called_at' => time(), 'state' => 0]);
$SybOil->saveLogStore('加油回调处理成功了:'.json_encode($res));
}else{
$SybOil->saveLogStore('没有处理结果:【'.$message.'】');
}
break;
case "oil":
// 分油结果通知
$where = array(
['shareNo', '=', $res['trade_no']],
);
$orderGoods = Db::name('order_goods')
->where($where)
->find();
if($orderGoods['order_goods_id'] && $res['useStatus'] == '1') {
$field = ['oil_time' => time()];
$field['oil_status'] = 1;
$field['qrCode'] = $res['useUrl'] ?? '';
Db::name('order_goods')
->where('order_goods_id', $orderGoods['order_goods_id'])
->update($field);
$SybOil->saveLogStore('分油回调处理成功了:'.json_encode($res));
}else{
// $this->queueService->push('callback_queue', json_encode(['header'=>$headers,'res'=>$res],320));
// $SybOil->saveLogStore('重新加入队列:【'.$message.'】');
}
break;
case "use_partners":
// 油卡变动通知
$where = array(
['shareNo', '=', $res['trade_no']],
);
$order = Db::name('partners_order')
->where($where)
->find();
$res['order_id'] = $order['order_id'];
$res['order_goods_id'] = $order['goods_id'];
$res['user_id'] = 0;
$res['store_id'] = $order['store_id'];
$res['optType'] = 'add_oil';
$RecordModel = new RecordModel();
// 油卡变动记录写入结果
$RecordModel->add($res);
// 更新油券使用状态
if($order['order_id'] && $res['useStatus'] == '2'){
Db::name('partners_order')
->where('order_id', $order['order_id'])
->update(array(
'use_status' => 1,
'use_time' => time(),
'use_text' => '加油',
));
$SybOil->saveLogStore('加油回调处理成功了:'.json_encode($res));
// 通知对接公司
$queueService = new QueueService();
$queueService->push('notify_queue', json_encode([
'order_id' => $order['order_id'],
'optType' => 'add_oil',
'retry_count' => 0,
], 320));
}else{
$SybOil->saveLogStore('没有处理结果:【'.$message.'】');
}
break;
case "oil_partners":
// 分油结果通知
$where = array(
['shareNo', '=', $res['trade_no']],
);
$order = Db::name('partners_order')
->where($where)
->find();
if($order['order_id'] && $res['useStatus'] == '1') {
$field = ['oil_time' => time()];
$field['oil_status'] = 1;
$field['qrCode'] = $res['useUrl'] ?? '';
Db::name('partners_order')
->where('order_id', $order['order_id'])
->update($field);
$SybOil->saveLogStore('分油回调处理成功了:'.json_encode($res));
// 通知对接公司
$queueService = new QueueService();
$queueService->push('notify_queue', json_encode([
'order_id' => $order['order_id'],
'optType' => 'share_oil',
'retry_count' => 0,
], 320));
}else{
// $this->queueService->push('callback_queue', json_encode(['header'=>$headers,'res'=>$res],320));
// $SybOil->saveLogStore('重新加入队列:【'.$message.'】');
}
break;
default:
$SybOil->saveLogStore('队列数据处理异常,未知:【'.$message.'】');
}
} catch (\Exception $e) {
$SybOil->saveLogStore(
'队列回调处理异常:' . $e->getMessage() .
' 在文件:' . $e->getFile() .
' 第:' . $e->getLine() .
' 行。堆栈跟踪:' . $e->getTraceAsString()
);
}
}
}
@@ -0,0 +1,128 @@
<?php
namespace app\console\command;
use app\store\model\User as UserModel;
use app\common\service\QueueService;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\store\model\card\CardLog as CardLogModel;
use app\common\service\SybOil;
use think\facade\Db;
class CardQueue extends Command
{
protected $queueService;
protected function configure()
{
$this->setName('card:queue')
->setDescription('Process messages from the Redis queue');
}
protected function execute(Input $input, Output $output)
{
$this->queueService = new QueueService();
while (true) {
$message = $this->queueService->pop('card_queue');
if ($message) {
// 处理消息
$this->processMessage($message);
} else {
// 暂停一段时间再检查队列
sleep(1);
}
}
}
protected function processMessage($message)
{
$SybOil = new SybOil();
// 拿到队列数据处理
$data = json_decode($message, true);
$SybOil->saveLogStore('card_queue队列数据处理:【'.$message.'】');
$userId = $data['user_id'];
$cardId = $data['card_id'];
// 查询兑换卡
$card = Db::name('card')
->where('card_id', $cardId)
->find();
$field = [
'card_id'=>$cardId,
'card_number'=>$card['card_number'],
'user_id'=>$userId,
'money'=>$card['amount'],
'store_id'=>$card['store_id'],
];
if ($card['is_used'] != 10) {
CardLogModel::add(array_merge(
[
'state'=>10,
'describe'=>'实体兑换卡已使用',
],
$field
));
return false; // 无效的卡或密钥
}
Db::startTrans();
try {
// 更新兑换卡使用状态
$affectedRows = Db::name('card')
->where('card_id', $card['card_id'])
->where('version', $card['version'])
->update([
'is_used' => 20,
'used_time' => time(),
'user_id' => $userId,
'version' => $card['version'] + 1,
]);
if ($affectedRows === 0) {
Db::rollback();
// 增加兑换记录
CardLogModel::add(array_merge(
[
'state'=>10,
'describe'=>'兑换失败,已使用',
],
$field
));
return false;
}
// 更新用户余额
$obj = UserModel::detail($userId);
// 增加分销对象的余额
$inc = $obj->exchangeToBalance($obj['mobile'],[
'money'=>$card['amount'],
'mode'=>'inc',
'remark'=>'实体卡兑换',
], $card['store_id']);
if(!$inc){
Db::rollback();
CardLogModel::add(array_merge(
[
'state'=>10,
'describe'=>'增加用户余额失败',
],
$field
));
return false;
}
// 增加兑换记录
CardLogModel::add(array_merge(
[
'state'=>20,
'describe'=>'兑换成功',
],
$field
));
Db::commit();
return true;
} catch (\Exception $e) {
$SybOil->saveLogStore($e->getMessage());
Db::rollback();
return false;
}
}
}
@@ -0,0 +1,130 @@
<?php
namespace app\console\command;
use app\common\service\PartnersOil;
use app\common\service\QueueService;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\common\model\partners\Order as OrderModel;
use app\common\model\Partners as partnersModel;
use think\facade\Db;
use think\facade\Log;
class NotifyQueue extends Command
{
protected $queueService;
protected function configure()
{
$this->setName('notify:queue')
->setDescription('Process messages from the Redis queue');
}
protected function execute(Input $input, Output $output)
{
$this->queueService = new QueueService();
while (true) {
// 先迁移到期的延迟任务
$this->queueService->migrateDelayedToReady('notify_queue');
$message = $this->queueService->pop('notify_queue');
if ($message) {
// 处理消息
$data = json_decode($message, true);
// 如果没有重试计数,默认 0
$retryCount = isset($data['retry_count']) ? intval($data['retry_count']) : 0;
$orderId = $data['order_id'] ?? null;
if (!$orderId) {
Log::error("队列消息缺少 order_id: " . $message);
continue;
}
// 调用回调接口
$success = $this->notifyPartner($data);
if ($success) {
Log::info("订单 {$orderId} 回调成功");
} else {
Log::warning("订单 {$orderId} 第 {$retryCount} 次回调失败");
if ($retryCount < 3) {
$retryCount++;
$delay = $this->getDelayTime($retryCount);
// 重新放回延迟队列
$data['retry_count'] = $retryCount;
$this->queueService->laterPush('notify_queue', json_encode($data, 320), $delay);
Log::info("订单 {$orderId} 已重新入队,延迟 {$delay} 秒后再通知");
} else {
Log::error("订单 {$orderId} 回调失败超过最大次数,放弃重试");
}
}
} else {
// 暂停一段时间再检查队列
sleep(1);
}
}
}
/**
* 模拟发送回调
* @param array $data
* @return bool
*/
protected function notifyPartner($data)
{
$order = OrderModel::detail($data['order_id']);
if(!$order){
return false;
}
$partners = partnersModel::detail($order['partners_id']);
if(!$partners){
return false;
}
$partnersOil = new PartnersOil();
$data = [
'oilCardNo' => $order['oilCardNo'],
'amount' => $order['total_price'],
'shareNo' => $order['shareNo'],
'type' => $data['optType'] == 'share_oil' ? 'add' : 'sub',
'optType' => $data['optType'],
];
$header['method'] = 'syb.notify.oilCard.change';
$res = $partnersOil->sendRequest($partners, $partners['callback'], $data, $header);
$code = $res['code'] ?? '';
if($res && $code == '00'){
if($data['optType'] == 'share_oil') {
$order->save([
'oil_callback' => 1,
'oil_callback_time' => time(),
]);
}else{
$order->save([
'use_callback' => 1,
'use_callback_time' => time(),
]);
}
return true;
}
return false;
}
/**
* 延迟时间策略
*/
private function getDelayTime($retryCount)
{
switch ($retryCount) {
case 1: return 60; // 1分钟
case 2: return 300; // 5分钟
case 3: return 1800; // 30分钟
default: return 0;
}
}
}
@@ -0,0 +1,140 @@
<?php
namespace app\console\command;
use app\common\service\IdingjuOil;
use app\common\service\QueueService;
use app\store\model\Company as CompanyModel;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\common\model\partners\Order as OrderModel;
use think\facade\Db;
class PartnersQueue extends Command
{
protected $queueService;
protected function configure()
{
$this->setName('partners:queue')
->setDescription('Process messages from the Redis queue');
}
protected function execute(Input $input, Output $output)
{
$this->queueService = new QueueService();
while (true) {
$message = $this->queueService->pop('partners_queue');
if ($message) {
// 处理消息
$this->processMessage($message);
} else {
// 暂停一段时间再检查队列
sleep(1);
}
}
}
protected function processMessage($message)
{
$IdingjuOil = new IdingjuOil();
$IdingjuOil->saveLogStore('partners_queue队列数据处理:【'.$message.'】');
// 拿到队列数据处理
$data = json_decode($message, true);
// 检查解码是否成功
if ($data === false) {
$IdingjuOil->saveLogStore('partners_queue队列数据解码失败:' . json_last_error_msg());
return;
}
$order = OrderModel::detail($data['order_id']);
if (!$order) {
$IdingjuOil->saveLogStore('未找到对应订单:【' . $data['order_id'] . '】');
return;
}
// 此处可以根据业务逻辑处理接收到的数据
try {
if($order['order_status'] == 10 && $order['oil_status'] == 0 && $order['oilCardType'] == 'zsy_ticket'){
$data['amount'] = $order['total_price']; // 金额
$company = CompanyModel::detail(['orgNo' => $this->getCompany($order['goods_no'])]);
if (!$company) {
$IdingjuOil->saveLogStore('没有可用参数:【' . $order['goods_no'] . '】');
return;
}
// 对接平台接口
$res = $IdingjuOil->oilOilCardShare([
'goodsNo'=>$order['goods_no'],
'amount'=>$data['amount'],
'userNo'=>'',
'mobile'=>$order['mobile'],
'saleOrderNo'=>$order['oilCardNo'],
'oilCardType'=>$order['oilCardType'],
'notify_url'=>config('app.base_url') . 'partnersoil.php',
'use_notify_url'=>config('app.base_url') . 'partnersoiluse.php'
], $company);
if ($res['code'] != 1) {
$IdingjuOil->saveLogStore(($res['errMessage'] ?? $res['message']));
return;
}
$item['shareNo'] = $res['data']['trade_no'] ?? '';
$item['qrCode'] = $res['data']['useUrl'] ?? '';
$item['oil_status_zsy'] = $res['data']['state'] ?? 0;
$item['oil_time'] = time();
$item['oil_status'] = $item['oil_status_zsy'] == 2 ? 1 : 0; // 已发券 为1
$resUpdate = $order->save($item);
if (!$resUpdate) {
$IdingjuOil->saveLogStore("订单更新失败,order_id: {$data['order_id']}");
}
if($item['oil_status_zsy'] == 2) {
// 存入队列处理
$queueService = new QueueService();
$queueService->push('notify_queue', json_encode([
'order_id' => $order['order_id'],
'type' => 'add',
'optType' => 'share_oil',
'retry_count' => 0,
], 320));
}
}
} catch (\Exception $e) {
$IdingjuOil->saveLogStore(
'partners_queue队列处理异常:' . $e->getMessage() .
' 在文件:' . $e->getFile() .
' 第:' . $e->getLine() .
' 行。堆栈跟踪:' . $e->getTraceAsString()
);
}
}
/**
* @param $goodsNo
* @return string
*/
public function getCompany($goodsNo): string
{
switch ($goodsNo) {
case 'djgdface100':
case 'djgdface200':
case 'djgdface300':
return 'umQZhIHKofyA';
case 'jmgxyyface100':
case 'jmgxyyface200':
case 'jmgxyyface300':
case 'jmgzface100':
case 'jmgzface200':
case 'jmgzface300':
case 'jmfjface100':
case 'jmfjface200':
case 'jmfjface300':
return 'HpWqXIgYvTBg';
case 'face003':
return 'NKJBgaaRNdiL'; // 测试参数
default:
return '';
}
}
}
@@ -0,0 +1,54 @@
<?php
namespace app\console\command;
use app\common\service\QueueService;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\store\model\Account as AccountModel;
use app\store\model\Company as CompanyModel;
use app\common\service\SybOil;
class ProcessQueue extends Command
{
protected $queueService;
protected function configure()
{
$this->setName('process:queue')
->setDescription('Process messages from the Redis queue');
}
protected function execute(Input $input, Output $output)
{
$this->queueService = new QueueService();
while (true) {
$message = $this->queueService->pop('account_queue');
if ($message) {
// 处理消息
$this->processMessage($message);
} else {
// 暂停一段时间再检查队列
sleep(1);
}
}
}
protected function processMessage($message)
{
$SybOil = new SybOil();
// 在这里处理回调数据
$SybOil->saveLogStore('account_queue队列数据处理:【'.$message.'】');
$account = AccountModel::detail($message);
$company = CompanyModel::detail($account['company_id']);
// 对接平台接口
$res = $SybOil->userOptAdd(['mobile'=>$account['mobile'],'userName'=>$account['userName'],'userIdCard'=>$account['userIdCard'],'userType'=>$account['userType']], $company);
if($res['code'] == '00' && isset($res['data']['userNo'])){
$data['userNo'] = $res['data']['userNo'];
$account->edit($data);
}else{
$SybOil->saveLogStore('平台创建用户失败【'.($res['errMessage'] ?? $res['message']).'】');
}
}
}
+106
View File
@@ -0,0 +1,106 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Event;
use Workerman\Worker;
/**
* 定时器 (Workerman)
* 用于执行系统里的定时任务, 例如自动确认收货
* 使用方法: 打开命令行 - 执行命令: php think timer start
* Class Timer
* @package app\common\command
*/
class Timer extends Command
{
// 定时器句柄/ID
protected $timer;
// 时间间隔 (单位: 秒, 默认5秒)
protected $interval = 1;
protected function configure()
{
// 指令配置
$this->setName('timer')
->addArgument('status', Argument::REQUIRED, 'start/stop/reload/status/connections')
->addOption('d', null, Option::VALUE_NONE, 'daemon(守护进程)方式启动')
->addOption('i', null, Option::VALUE_OPTIONAL, '多长时间执行一次')
->setDescription('start/stop/restart 定时任务');
}
protected function init(Input $input, Output $output)
{
global $argv;
if ($input->hasOption('i'))
$this->interval = floatval($input->getOption('i'));
$argv[1] = $input->getArgument('status') ?: 'start';
if ($input->hasOption('d')) {
$argv[2] = '-d';
} else {
unset($argv[2]);
}
}
/**
* 创建定时器
* @param Input $input
* @param Output $output
* @return int|void|null
*/
protected function execute(Input $input, Output $output)
{
$this->init($input, $output);
// 创建定时器任务
$worker = new Worker();
$worker->onWorkerStart = [$this, 'start'];
$worker->runAll();
}
/**
* 定时器执行的内容
* @return false|int
*/
public function start()
{
// 每隔n秒执行一次
return $this->timer = \Workerman\Lib\Timer::add($this->interval, function () {
try {
// 这里执行系统预设的定时任务事件
echo 'timer...' . PHP_EOL;
Event::trigger('StoreTask');
} catch (\Throwable $e) {
echo 'ERROR: ' . $e->getMessage() . PHP_EOL;
$this->stop();
}
});
}
/**
* 停止/删除定时器
* @return bool
*/
public function stop(): bool
{
return \Workerman\Lib\Timer::del($this->timer);
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\library;
/**
* 工具类
* Class Tools
* @package app\console\library
*/
class Tools
{
/**
* 为定时任务写日志
* @param string $taskKey
* @param string $method
* @param array $param
*/
static function taskLogs(string $taskKey, string $method, array $param = [])
{
return log_record(['name' => '定时任务', 'Task-Key' => $taskKey, 'method' => $method, 'param' => $param]);
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\Express as ExpressModel;
/**
* 物流公司模型
* Class Express
* @package app\console\model
*/
class Express extends ExpressModel
{
}
+25
View File
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\Goods as GoodsModel;
/**
* 商品模型
* Class Goods
* @package app\console\model
*/
class Goods extends GoodsModel
{
}
+25
View File
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\GoodsSku as GoodsSkuModel;
/**
* 商品规格模型
* Class GoodsSku
* @package app\console\model
*/
class GoodsSku extends GoodsSkuModel
{
}
+173
View File
@@ -0,0 +1,173 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\enum\order\DeliveryStatus;
use app\common\enum\order\ReceiptStatus;
use app\common\model\Order as OrderModel;
use app\common\enum\order\PayStatus as PayStatusEnum;
use app\common\enum\order\OrderStatus as OrderStatusEnum;
use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum;
/**
* 订单模型
* Class Order
* @package app\common\model
*/
class Order extends OrderModel
{
/**
* 获取订单列表
* @param int $storeId 商城ID
* @param array $filter
* @param array $with
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getList(int $storeId, $filter = [], $with = [])
{
return $this->with($with)
->where($filter)
->where('store_id', '=', $storeId)
->where('is_delete', '=', 0)
->select();
}
/**
* 获取订单ID集
* @param int $storeId 商城ID
* @param array $filter
* @return array
*/
public function getOrderIds(int $storeId, $filter = [])
{
return $this->where($filter)
->where('store_id', '=', $storeId)
->where('is_delete', '=', 0)
->column('order_id');
}
/**
* 查询截止时间未支付的订单列表
* @param int $storeId 商城ID
* @param int $deadlineTime 截止日期的时间戳
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getListByClose(int $storeId, int $deadlineTime)
{
// 查询条件
$filter = [
['pay_status', '=', PayStatusEnum::PENDING],
['order_status', '=', OrderStatusEnum::NORMAL],
['create_time', '<=', $deadlineTime],
];
// 查询列表记录
return $this->getList($storeId, $filter, ['goods', 'user']);
}
/**
* 查询截止时间已完成的订单列表
* @param int $storeId 商城ID
* @param array $orderIds 订单ID集
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getListByOrderIds(int $storeId, array $orderIds)
{
// 查询条件
$filter = [['order_id', 'in', $orderIds]];
// 查询列表记录
return $this->getList($storeId, $filter, ['goods' => ['refund']]);
}
/**
* 查询截止时间未确认收货的订单ID集
* @param int $storeId 商城ID
* @param int $deadlineTime 截止时间
* @return array
*/
public function getOrderIdsByReceive(int $storeId, int $deadlineTime)
{
// 查询条件
$filter = [
['pay_status', '=', PayStatusEnum::SUCCESS],
['delivery_status', '=', DeliveryStatus::DELIVERED],
['receipt_status', '=', ReceiptStatus::NOT_RECEIVED],
['delivery_time', '<=', $deadlineTime]
];
// 查询列表记录
return $this->getOrderIds($storeId, $filter);
}
/**
* 查询截止时间确认收货的订单列表
* @param int $storeId 商城ID
* @param int $deadlineTime 截止时间
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOrderListBySettled(int $storeId, int $deadlineTime)
{
// 查询条件
$filter = [
['order_status', '=', OrderStatusEnum::COMPLETED],
['receipt_time', '<=', $deadlineTime],
['is_settled', '=', 0]
];
// 查询列表记录
return $this->getList($storeId, $filter, ['goods.refund']);
}
/**
* 批量更新订单状态为已收货
* @param array $orderIds
* @return false|int
*/
public function onUpdateReceived(array $orderIds)
{
return $this->onBatchUpdate($orderIds, [
'receipt_status' => ReceiptStatus::RECEIVED,
'receipt_time' => time(),
// 'order_status' => OrderStatusEnum::COMPLETED
]);
}
/**
* 查询已完成未发货的订单
* @param int $storeId 商城ID
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getListByDelivery(int $storeId)
{
// 查询条件
$filter = [
['order_status', 'in', [OrderStatusEnum::NORMAL, OrderStatusEnum::COMPLETED]],
['transaction_id', '<>', ''],
['delivery_status', '=', DeliveryStatusEnum::NOT_DELIVERED],
];
// 查询列表记录
return $this->getList($storeId, $filter, ['goods', 'user']);
}
}
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\OrderAddress as OrderAddressModel;
/**
* 订单收货地址模型
* Class OrderAddress
* @package app\console\model
*/
class OrderAddress extends OrderAddressModel
{
}
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\OrderGoods as OrderGoodsModel;
/**
* 订单商品模型
* Class OrderGoods
* @package app\console\model
*/
class OrderGoods extends OrderGoodsModel
{
}
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\OrderRefund as OrderRefundModel;
/**
* 售后单模型
* Class OrderRefund
* @package app\console\model
*/
class OrderRefund extends OrderRefundModel
{
}
+25
View File
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\store\Setting as SettingModel;
/**
* 系统设置模型
* Class Wxapp
* @package app\console\model
*/
class Setting extends SettingModel
{
}
+37
View File
@@ -0,0 +1,37 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\Store as StoreModel;
/**
* 商家记录表模型
* Class Store
* @package app\admin\model
*/
class Store extends StoreModel
{
/**
* 获取商城ID集
* @param bool $isRecycle
* @return array
*/
public static function getStoreIds(bool $isRecycle = false)
{
$static = new static;
return $static->where('is_recycle', '=', (int)$isRecycle)
->where('is_delete', '=', 0)
->order(['create_time' => 'desc', $static->getPk()])
->column('store_id');
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\User as UserModel;
use app\common\model\user\Grade as UserGradeModel;
use app\console\model\user\GradeLog as GradeLogModel;
use app\common\enum\user\grade\log\ChangeType as ChangeTypeEnum;
/**
* 用户模型
* Class User
* @package app\console\model
*/
class User extends UserModel
{
/**
* 查询满足会员等级升级条件的用户列表
* @param int $storeId 商城ID
* @param UserGradeModel $upgradeGrade 会员等级
* @param array $excludedUserIds 排除的会员ID集
* @return mixed
*/
public static function getUpgradeUserList(int $storeId, UserGradeModel $upgradeGrade, $excludedUserIds = [])
{
// 实例化查询对象
$query = (new static)->getNewQuery();
// 检索查询条件
if (!empty($excludedUserIds)) {
$query->where('user.user_id', 'not in', $excludedUserIds);
}
// 查询列表记录
return $query->alias('user')
->field(['user.user_id', 'user.grade_id'])
->join('user_grade grade', 'grade.grade_id = user.grade_id', 'LEFT')
->where(function ($query) use ($upgradeGrade) {
$query->where('user.grade_id', '=', 0);
$query->whereOr('grade.weight', '<', $upgradeGrade['weight']);
})
->where('user.expend_money', '>=', $upgradeGrade['upgrade']['expend_money'])
->where('user.store_id', '=', $storeId)
->where('user.is_delete', '=', 0)
->select();
}
/**
* 批量设置会员等级
* @param int $storeId 商城ID
* @param array $data 会员等级更新数据
* @return bool
*/
public function setBatchGrade(int $storeId, array $data)
{
// 批量更新会员等级的数据
$userData = [];
// 批量新增会员等级变更记录的数据
$logData = [];
foreach ($data as $item) {
$userData[] = [
'where' => ['user_id' => $item['user_id']],
'data' => ['grade_id' => $item['new_grade_id']]
];
$logData[] = [
'user_id' => $item['user_id'],
'old_grade_id' => $item['old_grade_id'],
'new_grade_id' => $item['new_grade_id'],
'change_type' => ChangeTypeEnum::AUTO_UPGRADE,
'store_id' => $storeId,
];
}
// 批量更新会员等级
$this->updateAll($userData);
// 批量新增会员等级变更记录
(new GradeLogModel)->records($logData);
return true;
}
}
@@ -0,0 +1,54 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model;
use app\common\model\UserCoupon as UserCouponModel;
/**
* 用户优惠券模型
* Class UserCoupon
* @package app\console\model
*/
class UserCoupon extends UserCouponModel
{
// 是否允许全局查询store_id
protected $isGlobalScopeStoreId = false;
/**
* 获取已过期的优惠券ID集
* @param int $storeId
* @return array
*/
public function getExpiredCouponIds(int $storeId): array
{
$time = time();
return $this->where('is_expire', '=', 0)
->where('is_use', '=', 0)
->where('end_time', '<=', time())
->where('store_id', '=', $storeId)
->column('user_coupon_id');
}
/**
* 设置优惠券过期状态
* @param array $couponIds
* @return bool
*/
public function setIsExpire(array $couponIds): bool
{
if (empty($couponIds)) {
return false;
}
return $this->updateBase(['is_expire' => 1], [['user_coupon_id', 'in', $couponIds]]);
}
}
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model\recharge;
use app\common\model\recharge\Order as OrderModel;
/**
* 用户充值订单模型
* Class Order
* @package app\console\model\recharge
*/
class Order extends OrderModel
{
}
@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model\user;
use app\common\model\user\BalanceLog as BalanceLogModel;
/**
* 用户余额变动明细模型
* Class BalanceLog
* @package app\console\model\user
*/
class BalanceLog extends BalanceLogModel
{
}
@@ -0,0 +1,41 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model\user;
use app\common\model\user\Grade as GradeModel;
/**
* 用户会员等级模型
* Class Grade
* @package app\console\model\user
*/
class Grade extends GradeModel
{
/**
* 获取可用的会员等级列表
* @param int $storeId
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function getUsableList(int $storeId)
{
return (new static)->where('status', '=', 1)
->where('is_delete', '=', 0)
->where('store_id', '=', $storeId)
->order(['weight' => 'desc'])
->select();
}
}
@@ -0,0 +1,24 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model\user;
use app\common\model\user\GradeLog as GradeLogModel;
/**
* 用户会员等级变更记录模型
* Class GradeLog
* @package app\console\model\user
*/
class GradeLog extends GradeLogModel
{
}
@@ -0,0 +1,24 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\model\user;
use app\common\model\user\PointsLog as PointsLogModel;
/**
* 用户余额变动明细模型
* Class PointsLog
* @package app\console\model\user
*/
class PointsLog extends PointsLogModel
{
}
+194
View File
@@ -0,0 +1,194 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\service;
use app\common\enum\order\ReceiptStatus;
use app\common\model\UserOauth as UserOauthModel;
use app\console\model\Order as OrderModel;
use app\common\service\BaseService;
use app\common\service\Order as OrderService;
use app\common\service\order\Complete as OrderCompleteService;
use app\common\enum\order\OrderStatus as OrderStatusEnum;
use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum;
use app\common\library\helper;
use app\console\library\Tools;
use app\common\library\wechat\WxPay;
use app\common\model\wxapp\Setting as WxappSettingModel;
/**
* 服务类:订单模块
* Class Order
* @package app\console\service
*/
class Order extends BaseService
{
/**
* 未支付订单自动关闭
* @param int $storeId
* @param int $closeHours 自定关闭订单有效期 (小时)
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function closeEvent(int $storeId, int $closeHours)
{
// 截止时间
$deadlineTime = time() - ((int)$closeHours * 60 * 60);
// 查询截止时间未支付的订单
$model = new OrderModel;
$list = $model->getListByClose($storeId, $deadlineTime);
// 订单ID集
$orderIds = helper::getArrayColumn($list, 'order_id');
if (!empty($orderIds)) {
// 取消订单事件
foreach ($list as $order) {
OrderService::cancelEvent($order);
}
// 批量更新订单状态为已取消
$model->onBatchUpdate($orderIds, ['order_status' => OrderStatusEnum::CANCELLED]);
}
// 记录日志
Tools::taskLogs('Order', 'closeEvent', [
'storeId' => $storeId,
'closeHours' => $closeHours,
'deadlineTime' => $deadlineTime,
'orderIds' => helper::jsonEncode($orderIds)
]);
}
/**
* 已发货订单自动确认收货
* @param int $storeId
* @param int $receiveDays 自动收货天数
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function receiveEvent(int $storeId, int $receiveDays)
{
// 截止时间
$deadlineTime = time() - ((int)$receiveDays * 86400);
// 查询截止时间未确认收货的订单ID集
$model = new OrderModel;
$orderIds = $model->getOrderIdsByReceive($storeId, $deadlineTime);
// 更新订单收货状态
if (!empty($orderIds)) {
// 批量更新订单状态为已收货
$model->onUpdateReceived($orderIds);
// 批量处理已完成的订单
$this->onReceiveCompleted($storeId, $orderIds);
}
// 记录日志
Tools::taskLogs('Order', 'receiveEvent', [
'storeId' => $storeId,
'receiveDays' => $receiveDays,
'deadlineTime' => $deadlineTime,
'orderIds' => helper::jsonEncode($orderIds)
]);
}
/**
* 已完成订单自动结算
* @param int $storeId
* @param int $refundDays 售后期限天数
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function settledEvent(int $storeId, int $refundDays)
{
// 截止时间
$deadlineTime = time() - ((int)$refundDays * 86400);
// 查询截止时间确认收货的订单ID集
$model = new OrderModel;
$list = $model->getOrderListBySettled($storeId, $deadlineTime);
// 订单ID集
$orderIds = helper::getArrayColumn($list, 'order_id');
// 订单结算服务
if (!empty($orderIds)) {
$OrderCompleteService = new OrderCompleteService();
$OrderCompleteService->settled($list);
}
// 记录日志
Tools::taskLogs('Order', 'settledEvent', [
'storeId' => $storeId,
'refundDays' => $refundDays,
'deadlineTime' => $deadlineTime,
'orderIds' => helper::jsonEncode($orderIds)
]);
}
/**
* 批量处理已完成的订单
* @param int $storeId 商城ID
* @param array $orderIds 订单ID集
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function onReceiveCompleted(int $storeId, array $orderIds)
{
// 获取已完成的订单列表
$model = new OrderModel;
$list = $model->getListByOrderIds($storeId, $orderIds);
// 执行订单完成后的操作
if (!$list->isEmpty()) {
$OrderCompleteService = new OrderCompleteService();
$OrderCompleteService->complete($list, $storeId);
}
return true;
}
/**
* 自动微信支付发货
* @param int $storeId
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function deliveryEvent(int $storeId)
{
// 查询截止时间未支付的订单
$model = new OrderModel;
$list = $model->getListByDelivery($storeId);
// 订单ID集
$orderIds = helper::getArrayColumn($list, 'order_id');
if (!empty($orderIds)) {
// 小程序配置信息
$wxConfig = WxappSettingModel::getWxappConfig($storeId);
$wxPay = new WxPay(['app_id' => $wxConfig['app_id'], 'app_secret'=> $wxConfig['app_secret']]);
// 取消订单事件
foreach ($list as $order) {
// 请求API数据
$name = $order['goods'][0]['goods_name'] ?? '中石油油券';
// 获取第三方用户信息(微信)
$oauth = UserOauthModel::getOauth($order['user_id'], 'MP-WEIXIN');
$wxPay->uploadShipping($order['transaction_id'], $name, $oauth['oauth_id']);
}
// 批量更新订单状态为已取消
$model->onBatchUpdate($orderIds, [
'delivery_status' => DeliveryStatusEnum::DELIVERED,
'delivery_time' => time(),
'receipt_status' => ReceiptStatus::RECEIVED,
'receipt_time' => time()
]);
}
// 记录日志
Tools::taskLogs('Order', 'deliveryEvent', [
'storeId' => $storeId,
'orderIds' => helper::jsonEncode($orderIds)
]);
}
}
@@ -0,0 +1,45 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\service;
use app\common\library\helper;
use app\console\library\Tools;
use app\common\service\BaseService;
use app\console\model\UserCoupon as UserCouponModel;
/**
* 服务类:用户优惠券
* Class Order
* @package app\console\service
*/
class UserCoupon extends BaseService
{
/**
* 设置优惠券过期状态
* @param int $storeId
* @return bool
*/
public function setExpired(int $storeId): bool
{
$model = new UserCouponModel;
// 获取已过期的优惠券ID集
$couponIds = $model->getExpiredCouponIds($storeId);
// 记录日志
Tools::taskLogs('UserCoupon', 'setExpired', [
'storeId' => $storeId,
'couponIds' => helper::jsonEncode($couponIds)
]);
// 更新已过期状态
return $model->setIsExpire($couponIds);
}
}
@@ -0,0 +1,78 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\service;
use app\common\library\helper;
use app\console\library\Tools;
use app\common\service\BaseService;
use app\console\model\User as UserModel;
use app\console\model\user\Grade as UserGradeModel;
/**
* 服务类:会员等级
* Class UserGrade
* @package app\console\service
*/
class UserGrade extends BaseService
{
/**
* 设置用户的会员等级
* @param int $storeId
* @return array|bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function setUserGrade(int $storeId)
{
// 获取所有会员等级
$list = $this->getUsableList($storeId);
// 遍历等级,根据升级条件 查询满足消费金额的用户列表,并且他的等级小于该等级
$data = [];
foreach ($list as $grade) {
// 查询满足会员等级升级条件的用户列表
$userList = UserModel::getUpgradeUserList($storeId, $grade, array_keys($data));
// 遍历整理数据
foreach ($userList as $user) {
if (!isset($data[$user['user_id']])) {
$data[$user['user_id']] = [
'user_id' => $user['user_id'],
'old_grade_id' => $user['grade_id'],
'new_grade_id' => $grade['grade_id'],
];
}
}
}
// 记录日志
Tools::taskLogs('UserGrade', 'setUserGrade', [
'storeId' => $storeId,
'data' => $data
]);
// 批量修改会员的等级
return (new UserModel)->setBatchGrade($storeId, $data);
}
/**
* 获取所有会员等级
* @param int $storeId 商城ID
* @return false|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getUsableList(int $storeId)
{
return UserGradeModel::getUsableList($storeId);
}
}
+136
View File
@@ -0,0 +1,136 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\task;
use app\console\service\Order as OrderService;
use app\console\model\Setting as SettingModel;
use think\facade\Cache;
/**
* 定时任务:商城订单
* Class Order
* @package app\console\task
*/
class Order extends Task
{
// 当前任务唯一标识
private $taskKey = 'Order';
// 任务执行间隔时长 (单位:秒)
protected $taskExpire = 60 * 30;
// 当前商城ID
private $storeId;
/**
* 任务处理
* @param array $param
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function handle(array $param)
{
['storeId' => $this->storeId] = $param;
// Cache::delete("Listener:{$this->storeId}:Order"); //手动执行时,开启清楚缓存,以便立即执行
$this->setInterval($this->storeId, $this->taskKey, $this->taskExpire, function () {
echo $this->taskKey . PHP_EOL;
// 未支付订单自动关闭
$this->closeEvent();
// 已发货订单自动确认收货
// $this->receiveEvent();
// 已完成订单结算
$this->settledEvent();
// 自动微信支付发货
$this->deliveryEvent();
});
}
/**
* 未支付订单自动关闭
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function closeEvent()
{
// 自动关闭订单的有效期
$closeHours = (int)$this->getTradeSetting()['closeHours'];
// 执行自动关闭
if ($closeHours > 0) {
$service = new OrderService;
$service->closeEvent($this->storeId, $closeHours);
}
}
/**
* 自动确认收货订单的天数
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function receiveEvent()
{
// 取消n天以前的的未付款订单
$receiveDays = (int)$this->getTradeSetting()['receive_days'];
// 执行自动确认收货
if ($receiveDays > 0) {
$service = new OrderService;
$service->receiveEvent($this->storeId, $receiveDays);
}
}
/**
* 已完成订单自动结算
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function settledEvent()
{
// 取消n天以前的的未付款订单
$refundDays = (int)$this->getTradeSetting()['refund_days'];
// 执行自动确认收货
if ($refundDays > 0) {
$service = new OrderService;
$service->settledEvent($this->storeId, $refundDays);
}
}
/**
* 自动微信支付发货
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function deliveryEvent()
{
$service = new OrderService;
$service->deliveryEvent($this->storeId);
}
/**
* 获取商城交易设置
* @return array|mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getTradeSetting()
{
return SettingModel::getItem('trade', $this->storeId)['order'];
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\task;
use think\facade\Event;
use app\console\model\Store as StoreModel;
/**
* 商城定时任务
* Class StoreTask
* @package app\console\task
*/
class Store extends Task
{
/**
* 任务处理
*/
public function handle()
{
// 遍历商城列表并执行定时任务
$storeIds = StoreModel::getStoreIds();
foreach ($storeIds as $storeId) {
// echo $storeId . PHP_EOL;
// 定时任务:商城订单
Event::trigger('Order', ['storeId' => $storeId]);
// 定时任务:用户优惠券
Event::trigger('UserCoupon', ['storeId' => $storeId]);
// 定时任务:会员等级
Event::trigger('UserGrade', ['storeId' => $storeId]);
}
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\task;
use think\facade\Cache;
/**
* 定时任务监听器
* Class Listener
* @package app\console\task
*/
class Task
{
/**
* 定时执行任务
* @param int $storeId
* @param string $key
* @param int|null $expire
* @param callable $callback
* @return mixed
*/
protected function setInterval(int $storeId, string $key, int $expire, callable $callback)
{
if (!$this->hasTaskId($storeId, $key)) {
$this->setTaskId($storeId, $key, $expire);
return call_user_func($callback);
}
}
/**
* 获取任务ID
* @param int $storeId
* @param string $key
* @return bool
*/
protected function hasTaskId(int $storeId, string $key): bool
{
return Cache::has("Listener:$storeId:$key");
}
/**
* 设置任务ID
* 用于实现定时任务的间隔时间, 如果任务ID存在并未过期, 则不执行任务
* @param int $storeId
* @param string $key
* @param int $expire 任务ID过期时长(单位:秒)
* @return bool
*/
protected function setTaskId(int $storeId, string $key, int $expire = 60): bool
{
return Cache::set("Listener:$storeId:$key", true, $expire);
}
}
@@ -0,0 +1,56 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\task;
use app\console\service\UserCoupon as UserCouponService;
/**
* 定时任务:设置优惠券过期状态
* Class UserCoupon
* @package app\console\task
*/
class UserCoupon extends Task
{
// 当前任务唯一标识
private $taskKey = 'UserCoupon';
// 任务执行间隔时长 (单位:秒)
protected $taskExpire = 60 * 30;
// 当前商城ID
private $storeId;
/**
* 任务处理
* @param array $param
*/
public function handle(array $param)
{
['storeId' => $this->storeId] = $param;
$this->setInterval($this->storeId, $this->taskKey, $this->taskExpire, function () {
// echo $this->taskKey . PHP_EOL;
// 设置优惠券过期状态
$this->setExpired();
});
}
/**
* 设置优惠券过期状态
*/
private function setExpired()
{
$service = new UserCouponService;
$service->setExpired($this->storeId);
}
}
+62
View File
@@ -0,0 +1,62 @@
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\console\task;
use app\console\service\UserGrade as UserGradeService;
/**
* 定时任务:会员等级
* Class UserGrade
* @package app\console\task
*/
class UserGrade extends Task
{
// 当前任务唯一标识
private $taskKey = 'UserGrade';
// 任务执行间隔时长 (单位:秒)
protected $taskExpire = 60 * 30;
// 当前商城ID
private $storeId;
/**
* 任务处理
* @param array $param
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function handle(array $param)
{
['storeId' => $this->storeId] = $param;
$this->setInterval($this->storeId, $this->taskKey, $this->taskExpire, function () {
echo $this->taskKey . PHP_EOL;
// 设置用户的会员等级
$this->setUserGrade();
});
}
/**
* 设置用户的会员等级
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function setUserGrade()
{
$service = new UserGradeService;
$service->setUserGrade($this->storeId);
}
}