- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<?php
namespace addons\shopro\job;
use think\Log;
/**
* BaseJob 基类
*/
class BaseJob
{
public function failed($data)
{
// 失败队列,这里不用添加了, 后续程序会自动添加,这里可以发送邮件或者通知
// 记录日志
// \think\Db::name('shopro_failed_job')->insert([
// 'data' => json_encode($data),
// 'createtime' => time(),
// 'updatetime' => time()
// ]);
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace addons\shopro\job;
use think\queue\Job;
use think\Db;
use think\exception\HttpResponseException;
use addons\shopro\service\commission\Agent as AgentService;
/**
* 分销任务
*/
class Commission extends BaseJob
{
/**
* 分销商升级
*/
public function agentUpgrade(Job $job, $payload)
{
try {
$userId = $payload['user_id'];
$agent = new AgentService($userId);
if ($agent->user) {
Db::transaction(function () use ($agent) {
$agent->runAgentUpgradePlan();
});
}
$job->delete();
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'AgentUpgrade.HttpResponseException', $message);
} catch (\Exception $e) {
format_log_error($e, 'AgentUpgrade');
}
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace addons\shopro\job;
use think\exception\HttpResponseException;
use think\queue\Job;
use GuzzleHttp\Client;
/**
* 设计师模板图片转存
*/
class Designer extends BaseJob
{
protected $client = null;
/**
* 转存
*/
public function redeposit(Job $job, $data)
{
// 删除 job防止这个队列一直异常无法被删除
$job->delete();
try {
$imageList = $data['imageList'];
foreach ($imageList as $image) {
try {
// 路径转存图片,这里只保存到本地 public/storage 目录
$this->redepositSave($image, parse_url($image, PHP_URL_PATH));
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
\think\Log::error('设计师模板图片转存失败-HttpResponseException: ' . $message);
} catch (\Exception $e) {
\think\Log::error('设计师模板图片转存失败: ' . $e->getMessage());
}
}
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'Designer.redeposit.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'Designer.redeposit');
}
}
/**
* 转存到本地
*
* @param [type] $path
* @param [type] $save_path
* @return void
*/
private function redepositSave($path, $save_path)
{
$response = $this->getClient()->get($path);
$body = $response->getBody()->getContents(); // 图片数据流
$save_path = ROOT_PATH . 'public/' . ltrim($save_path, '/');
$save_dir = dirname($save_path);
if (!is_dir($save_dir)) {
@mkdir($save_dir, 0755, true);
}
file_put_contents($save_path, $body); // 转存本地
}
private function getClient()
{
if ($this->client) {
return $this->client;
}
return $this->client = new Client();
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace addons\shopro\job;
use think\queue\Job;
use think\Db;
use think\exception\HttpResponseException;
use app\admin\model\shopro\order\Order;
use app\admin\model\shopro\activity\Groupon;
use addons\shopro\library\activity\traits\Groupon as GrouponTrait;
/**
* 拼团自动操作
*/
class GrouponAutoOper extends BaseJob
{
use GrouponTrait;
/**
* 拼团判断,将团结束,
*/
public function expire(Job $job, $data)
{
if (check_env('yansongda', false)) {
set_addon_config('epay', ['version' => 'v3'], false);
\think\Hook::listen('epay_config_init');
}
try {
$activity = $data['activity'];
$activity_groupon_id = $data['activity_groupon_id'];
$activityGroupon = Groupon::where('id', $activity_groupon_id)->find();
// 活动正在进行中, 走这里的说明人数 都没满
if ($activityGroupon && $activityGroupon['status'] == 'ing') {
Db::transaction(function () use ($activity, $activityGroupon) {
$rules = $activity['rules'];
// 是否虚拟成团
$is_fictitious = $rules['is_fictitious'] ?? 0;
// 最大虚拟人数 ,不填或者 "" 不限制人数,都允许虚拟成团, 0相当于不允许虚拟成团
$fictitious_num = (!isset($rules['fictitious_num']) || $rules['fictitious_num'] === '') ? 'no-limit' : $rules['fictitious_num'];
// 拼团剩余人数
$surplus_num = $activityGroupon['num'] - $activityGroupon['current_num'];
if ($is_fictitious && ($fictitious_num == 'no-limit' || $fictitious_num >= $surplus_num)) {
// 虚拟成团,如果虚拟用户不够,则自动解散
$this->finishFictitiousGroupon($activity, $activityGroupon);
} else {
// 解散退款
$this->invalidRefundGroupon($activityGroupon);
}
});
}
// 删除 job
$job->delete();
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'GrouponAutoOper.expire.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'GrouponAutoOper.expire');
}
}
/**
* 拼团判断,提前虚拟成团
*/
public function fictitious(Job $job, $data)
{
try {
$activity = $data['activity'];
$activity_groupon_id = $data['activity_groupon_id'];
$activityGroupon = Groupon::where('id', $activity_groupon_id)->find();
// 活动正在进行中, 走这里的说明人数 都没满
if ($activityGroupon && $activityGroupon['status'] == 'ing') {
Db::transaction(function () use ($activity, $activityGroupon) {
$rules = $activity['rules'];
// 是否虚拟成团
$is_fictitious = $rules['is_fictitious'] ?? 0;
// 最大虚拟人数 ,不填或者 "" 不限制人数,都允许虚拟成团, 0相当于不允许虚拟成团
$fictitious_num = (!isset($rules['fictitious_num']) || $rules['fictitious_num'] === '') ? 'no-limit' : $rules['fictitious_num'];
// 拼团剩余人数
$surplus_num = $activityGroupon['num'] - $activityGroupon['current_num'];
if ($is_fictitious && ($fictitious_num == 'no-limit' || $fictitious_num >= $surplus_num)) {
// 虚拟成团,如果不符合成团条件,则不处理
$this->finishFictitiousGroupon($activity, $activityGroupon, false);
}
});
}
// 删除 job
$job->delete();
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'GrouponAutoOper.fictitious.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'GrouponAutoOper.fictitious');
}
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace addons\shopro\job;
use think\queue\Job;
use think\exception\HttpResponseException;
/**
* 队列消息通知
*/
class Notification extends BaseJob
{
/**
* 发送通知
*/
public function send(Job $job, $data)
{
// 删除 job防止这个队列一直异常无法被删除
$job->delete();
try {
// 这里获取到的 $notifiables 和 notification 两个都是数组,不是类,尴尬, 更可恨的 notification 只是 {"delay":0,"event":"changemobile"}
$notifiables = $data['notifiables'];
$notification = $data['notification'];
// 因为 notification 只有参数,需要把对应的类传过来,在这里重新初始化
$notification_name = $data['notification_name'];
$notifiable_name = $data['notifiable_name'];
// 重新实例化 notification 实例
if (class_exists($notification_name)) {
$notification = new $notification_name($notification['data']);
}
// 重新实例化 notifiable
if (class_exists($notifiable_name)) {
$notifiable = new $notifiable_name();
$notifiables = $notifiable->where('id', 'in', array_column($notifiables, 'id'))->select();
}
// 发送消息
\addons\shopro\library\notify\Notify::sendNow($notifiables, $notification);
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'Notification.send.HttpResponseException', $message);
} catch (\Exception $e) {
format_log_error($e, 'Notification.send.' . ($notification->event ?? ''));
}
}
}

View File

@@ -0,0 +1,155 @@
<?php
namespace addons\shopro\job;
use think\queue\Job;
use think\Log;
use think\Db;
use think\Collection;
use think\exception\HttpResponseException;
use addons\shopro\exception\ShoproException;
use app\admin\model\shopro\order\Order;
use app\admin\model\shopro\order\OrderItem;
use addons\shopro\service\order\OrderOper;
use app\admin\model\shopro\order\Action;
/**
* 订单自动操作
*/
class OrderAutoOper extends BaseJob
{
/**
* 订单自动关闭
*/
public function autoClose(Job $job, $data){
if (check_env('yansongda', false)) {
set_addon_config('epay', ['version' => 'v3'], false);
\think\Hook::listen('epay_config_init');
}
try {
$order = $data['order'];
// 重新查询订单
$order = Order::unpaid()->where('id', $order['id'])->find();
if ($order) {
Db::transaction(function () use ($order, $data) {
$orderOper = new OrderOper();
$order = $orderOper->close($order, null, 'system');
return $order;
});
}
// 删除 job
$job->delete();
} catch (ShoproException $e) {
// 自定义异常时删除 队列
$job->delete();
format_log_error($e, 'OrderAutoOper.autoClose.sheepException');
} catch (HttpResponseException $e) {
// error_stop 异常时删除 队列
$job->delete();
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'OrderAutoOper.autoClose.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'OrderAutoOper.autoClose');
}
}
/**
* 订单自动确认收货
*/
public function autoConfirm(Job $job, $data) {
try {
$order = $data['order'];
$items = $data['items'];
$itemIds = $items instanceof Collection ? $items->column('id') : array_column($items, 'id');
// 重新查询订单
$order = Order::paid()->where('id', $order['id'])->find(); // 货到付款的 还未付款的订单被排除在外,不会自动收货
if ($order) {
$order = Db::transaction(function () use ($order, $itemIds) {
$orderOper = new OrderOper();
$order = $orderOper->confirm($order, $itemIds, null, 'system');
return $order;
});
}
// 删除 job
$job->delete();
} catch (ShoproException $e) {
// 自定义异常时删除 队列
$job->delete();
format_log_error($e, 'OrderAutoOper.autoConfirm.sheepException');
} catch (HttpResponseException $e) {
// error_stop 异常时删除 队列
$job->delete();
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'OrderAutoOper.autoConfirm.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'OrderAutoOper.autoConfirm');
}
}
public function autoComment(Job $job, $data) {
try {
$order = $data['order'];
$item = $data['item'];
// 重新查询订单
$order = Order::paid()->where('id', $order['id'])->find();
if ($order && $item) {
$order = Db::transaction(function () use ($order, $item) {
$orderOper = new OrderOper();
$comments[] = [
'item_id' => $item['id'],
'level' => 5,
];
// 评价一个订单商品
$order = $orderOper->comment($order, $comments, null, 'system');
return $order;
});
}
// 删除 job
$job->delete();
} catch (ShoproException $e) {
// 自定义异常时删除 队列
$job->delete();
format_log_error($e, 'OrderAutoOper.autoComment.sheepException');
} catch (HttpResponseException $e) {
// error_stop 异常时删除 队列
$job->delete();
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'OrderAutoOper.autoComment.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'OrderAutoOper.autoComment');
$job->delete();
}
}
}

View File

@@ -0,0 +1,113 @@
<?php
namespace addons\shopro\job;
use think\queue\Job;
use think\Db;
use think\exception\HttpResponseException;
use app\admin\model\shopro\order\Order;
use addons\shopro\service\StockSale;
use app\admin\model\shopro\user\User;
use app\admin\model\shopro\order\Invoice as OrderInvoice;
use addons\shopro\service\order\OrderOper;
use addons\shopro\facade\Activity as ActivityFacade;
/**
* 订单自动操作
*/
class OrderPaid extends BaseJob
{
/**
* 订单支付完成
*/
public function paid(Job $job, $data)
{
try {
$order = $data['order'];
$user = $data['user'];
$order = Order::with('items')->where('id', $order['id'])->find();
$user = User::get($user['id']);
// 数据库删订单的问题常见,这里被删的订单直接把队列移除
if ($order) {
Db::transaction(function () use ($order, $user, $data) {
// 订单减库存
$stockSale = new StockSale();
$stockSale->forwardStockSale($order);
// 处理发票审核改为等待开具
if ($order->invoice_status == 1) {
$invoice = OrderInvoice::where('order_id', $order->id)->find();
if ($invoice) {
$invoice->status = 'waiting';
$invoice->save();
}
}
// 处理活动,加入拼团,完成拼团,添加赠品记录等
ActivityFacade::buyOk($order, $user);
// 将订单参与活动信息改为已支付
$orderOper = new OrderOper();
$orderOper->activityOrderPaid($order);
// 触发订单支付完成事件
$data = ['order' => $order, 'user' => $user];
\think\Hook::listen('order_paid_after', $data);
});
}
// 删除 job
$job->delete();
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'OrderPaid.paid.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'OrderPaid.paid');
}
}
/**
* 订单选择线下支付(货到付款)完成
*/
public function offline(Job $job, $data)
{
try {
$order = $data['order'];
$user = $data['user'];
$order = Order::with('items')->where('id', $order['id'])->find();
$user = User::get($user['id']);
// 数据库删订单的问题常见,这里被删的订单直接把队列移除
if ($order) {
Db::transaction(function () use ($order, $user, $data) {
// 订单减库存
$stockSale = new StockSale();
$stockSale->forwardStockSale($order);
// 处理活动,加入拼团,完成拼团,添加赠品记录等
ActivityFacade::buyOk($order, $user);
// 触发订单选择线下支付(货到付款)完成事件
$data = ['order' => $order, 'user' => $user];
\think\Hook::listen('order_offline_after', $data);
});
}
// 删除 job
$job->delete();
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'OrderPaid.offline.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'OrderPaid.offline');
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace addons\shopro\job;
use think\queue\Job;
class Test extends BaseJob
{
/**
* 普通优先级队列测试
*/
public function shopro(Job $job, $data)
{
// 创建目录
$this->mkdir();
// 写入日志文件
$filename = RUNTIME_PATH . 'storage/queue/shopro.log';
file_put_contents($filename, date('Y-m-d H:i:s'));
$job->delete();
}
/**
* 高优先级队列测试
*/
public function shoproHigh(Job $job, $data)
{
// 创建目录
$this->mkdir();
// 写入日志文件
$filename = RUNTIME_PATH . 'storage/queue/shopro-high.log';
file_put_contents($filename, date('Y-m-d H:i:s'));
$job->delete();
}
/**
* 创建目录
*/
private function mkdir()
{
$dir = RUNTIME_PATH . 'storage/queue/';
if (!is_dir($dir)) {
@mkdir($dir, 0755, true);
}
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace addons\shopro\job\trade;
use addons\shopro\job\BaseJob;
use think\queue\Job;
use think\Db;
use think\exception\HttpResponseException;
use addons\shopro\exception\ShoproException;
use app\admin\model\shopro\trade\Order;
/**
* 订单自动操作
*/
class OrderAutoOper extends BaseJob
{
/**
* 订单自动关闭
*/
public function autoClose(Job $job, $data)
{
try {
$order = $data['order'];
// 重新查询订单
$order = Order::unpaid()->where('id', $order['id'])->find();
if ($order) {
Db::transaction(function () use ($order, $data) {
// 执行关闭
$order->status = Order::STATUS_CLOSED;
$order->ext = array_merge($order->ext, ['closed_time' => time()]); // 取消时间
$order->save();
});
}
// 删除 job
$job->delete();
} catch (ShoproException $e) {
// 自定义异常时删除 队列
$job->delete();
format_log_error($e, 'TradeOrderAutoOper.autoClose.ShoproException');
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'TradeOrderAutoOper.autoClose.HttpResponseException', $message);
} catch (\Exception $e) {
// 队列执行失败
format_log_error($e, 'TradeOrderAutoOper.autoClose');
}
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace addons\shopro\job\trade;
use addons\shopro\job\BaseJob;
use think\queue\Job;
use think\Db;
use think\exception\HttpResponseException;
use app\admin\model\shopro\trade\Order;
use app\admin\model\shopro\user\User;
use addons\shopro\service\Wallet as WalletService;
use addons\shopro\facade\Wechat;
use addons\shopro\library\easywechatPlus\WechatMiniProgramShop;
/**
* 订单自动操作
*/
class OrderPaid extends BaseJob
{
/**
* 交易订单支付完成
*/
public function paid(Job $job, $data)
{
try {
$order = $data['order'];
$user = $data['user'];
$order = Order::where('id', $order['id'])->find();
$user = User::get($user['id']);
// 数据库删订单的问题常见,这里被删的订单直接把队列移除
if ($order) {
Db::transaction(function () use ($order, $user, $data) {
if ($order->type == 'recharge') {
// 充值
$ext = $order->ext;
$rule = $ext['rule'] ?? [];
$money = (isset($rule['money']) && $rule['money'] > 0) ? $rule['money'] : 0;
$gift_type = $rule['gift_type'] ?? 'money';
$gift = (isset($rule['gift']) && $rule['gift'] > 0) ? $rule['gift'] : 0;
if ($money > 0) {
// 增加余额
WalletService::change($user, 'money', $money, 'order_recharge', [
'order_id' => $order->id,
'order_sn' => $order->order_sn,
'order_type' => 'trade_order',
]);
}
if ($gift > 0) {
// 充值赠送
WalletService::change($user, $gift_type, $gift, 'recharge_gift', [
'order_id' => $order->id,
'order_sn' => $order->order_sn,
'order_type' => 'trade_order',
]);
}
}
$uploadshoppingInfo = new WechatMiniProgramShop(Wechat::miniProgram());
// 微信小程序,使用 微信支付, 并且存在微信发货管理权限时,才推送发货消息
if ($order->platform == 'WechatMiniProgram' && $order->pay_type == 'wechat' && $uploadshoppingInfo->isTradeManaged()) {
$uploadshoppingInfo->tradeUploadShippingInfos($order);
}
});
}
// 删除 job
$job->delete();
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
format_log_error($e, 'OrderPaid.paid.HttpResponseException', $message);
} catch (\Exception $e) {
format_log_error($e, 'OrderPaid.paid');
}
}
}