初始化项目:添加后端代码、ThinkPHP框架、前端资源

This commit is contained in:
amb
2026-09-03 12:42:39 +08:00
commit 482bece22e
3726 changed files with 416708 additions and 0 deletions
+262
View File
@@ -0,0 +1,262 @@
<?php
namespace app\common\behavior\order;
use app\common\model\user\Subscription;
use app\common\model\order\Item;
use app\admin\model\course\Course;
/**
* 支付成功
*/
class Payed
{
// 订单支付成功
public function run($order) {
$userId = $order->user_id;
//虚拟商品交易成功
if($order->order_type == 'physical'){
$order->status = \app\common\constant\order\Status::STATUS_UNSEND;
\app\common\model\order\Log::set($order->order_no,"订单已完成支付,等待发货");
$orderItemList = (new Item())->getItemList($order->order_no);
if(!empty($orderItemList)){
$stockSale = new \app\common\service\app\physical\StockSale();
$stockSale->forwardStockSale($orderItemList);
}
} else {
$order->status = \app\common\constant\order\Status::STATUS_SUCCESS;
//增加销量
\app\common\model\order\Log::set($order->order_no,"订单已完成交易");
// 订单支付成功
$this->courseSubscriptionBind($order);
}
$order->save();
//分销 检查升级
(new \app\api\model\app\agent\Level())->handle($userId);
//消息推送收集
\app\admin\library\app\msgpush\Msg::collect('order_success',['order_no'=>$order->order_no]);
}
/**
* 授权用户购买的课程
* @param $order
* @return bool
*/
public function courseSubscriptionBind($order){
$orderItemList = (new Item())->getItemList($order->order_no);
$SubscriptionModel = new Subscription();
if(!empty($orderItemList)){
foreach ($orderItemList as $orderItem){
switch ($order->order_type){
case 'vipcard':
$cardSku = explode("_",$orderItem['extend_data']);
if($cardSku){
\app\common\model\app\vip\CardUser::openVip($order->user_id,$orderItem['item_id'],$cardSku[1]);
}
break;
case 'live_gift':
$messageInfo = explode("_",$orderItem['extend_data']);
\app\common\model\live\Message::sendMessage($order->user_id,$messageInfo[0],$messageInfo[1],'gift',$orderItem['item_name']."×".$orderItem['count'],1);
//增加送礼物记录
\app\admin\model\live\GiftLog::insert([
'uniacid'=>UNIACID,
'live_id'=>$messageInfo[0],
'user_id'=>$order->user_id,
'order_no'=>$order->order_no,
'name'=>$orderItem['item_name'],
'price'=>$order->real_price,
'count'=>$orderItem['count'],
'createtime'=>time()
]);
break;
case 'exercises':
\app\common\model\app\exam\ExercisesSubscribe::subscribe($order->user_id,$orderItem['item_id'],'pay');
break;
case 'activity':
$ticketInfo = $orderItem->snapshoot;
\app\api\model\app\activity\Activity::setUserTicket($orderItem->user_id,$orderItem->item_id,$ticketInfo['ticket_id'],$ticketInfo['apply_info_id'],$orderItem->count,$orderItem->real_price,$orderItem->order_no,$orderItem->extend_data);
//增加销量
//活动增加销量
\app\api\model\app\activity\Activity::where(['id'=>$orderItem['item_id']])->setInc('sales');
//活动票也要增加
\app\api\model\app\activity\Ticket::where(['id'=>$ticketInfo['ticket_id']])->setInc('sales');
break;
case 'composite':
// 组合商品处理:授权子商品权限 + 增加销量
if (\app\admin\library\project\App::isInstall('composite')) {
$this->compositePurchaseHandle($orderItem, $order);
}
break;
default:
$this->addSales($orderItem['item_id'],$order);
$getType = '';
$mobile = '';
if($order->source == 'channels'){
$channelsOrder = \think\Db::name("app_channels_order")->where(['order_id'=>$order->order_no])->find();
if($channelsOrder){ $getType = 'channels'; $mobile = $channelsOrder['mobile']; }
}
$SubscriptionModel->setUserCourse($order->user_id,$orderItem['item_id'],$getType,$mobile);
break;
}
}
}
return true;
}
/**
* 增加销量
* @param $courseId
* @return void
*/
public function addSales($goodsId,$order){
switch ($order->order_type){
case 'score':
//积分商品增加销量 减少库存
$scoreGoodsModel = new \app\api\model\app\score\Goods;
$scoreGoodsModel->where(['goods_id'=>$goodsId])->setInc('sales');
$scoreGoodsModel->where(['goods_id'=>$goodsId])->setDec('stock');
break;
case 'goods':
Course::where(['id'=>$goodsId])->setInc('sales');
break;
}
return true;
}
/**
* 处理组合商品购买:授权子商品 + 增加销量
* @param array $orderItem 订单商品
* @param object $order 订单对象
*/
protected function compositePurchaseHandle($orderItem, $order)
{
$snapshoot = $orderItem['snapshoot'];
if (is_string($snapshoot)) {
$snapshoot = json_decode($snapshoot, true);
}
if (empty($snapshoot)) {
return;
}
$subGoodsList = $snapshoot['sub_goods_list'] ?? [];
$userId = $order->user_id;
$compositeGoodsId = $orderItem['item_id'];
// 授权每个子商品
$SubscriptionModel = new Subscription();
foreach ($subGoodsList as $subGoods) {
$subGoodsId = $subGoods['sub_goods_id'];
$subGoodsType = $subGoods['sub_goods_type'];
// 构建有效期覆盖配置(组合商品自定义有效期优先于商品本身有效期)
$validityOverride = null;
if (!empty($subGoods['validity_type']) && intval($subGoods['validity_type']) > 1) {
$validityOverride = [
'validity_type' => intval($subGoods['validity_type']),
'validity_value' => $subGoods['validity_value'] ?? '',
];
}
switch ($subGoodsType) {
case 'course':
// 视频/音频/图文/直播都统一为 course 授权
$SubscriptionModel->setUserCourse($userId, $subGoodsId, '', '', $validityOverride);
// 增加子商品销量
Course::where(['id' => $subGoodsId])->setInc('sales');
break;
case 'vipcard':
// 会员卡:从快照中取有效期信息
$cardSku = $subGoods['sub_goods_price'] . '_' . ($subGoods['validity_value'] ?? '30');
\app\common\model\app\vip\CardUser::openVip($userId, $subGoodsId, $cardSku);
break;
case 'exercises':
\app\common\model\app\exam\ExercisesSubscribe::subscribe($userId, $subGoodsId, 'pay');
// 增加练习销量
\think\Db::name('app_exam_exercises')->where(['id' => $subGoodsId])->setInc('sales');
break;
case 'audio':
case 'live':
case 'article':
case 'column':
// 音频/直播/图文/专栏统一存储于 tuzhi_course 表,按 id 累加销量
$SubscriptionModel->setUserCourse($userId, $subGoodsId, '', '', $validityOverride);
\think\Db::name('course')->where(['id' => $subGoodsId])->setInc('sales');
break;
}
}
// 增加组合商品自身销量
\app\admin\model\app\composite\Goods::where([
'id' => $compositeGoodsId,
'uniacid' => UNIACID
])->setInc('total_sales');
}
/**
* 处理组合商品退款:关闭子商品权限 + 返还销量
* @param array $orderItem 订单商品
* @param object $order 订单对象
* @param bool $isFullRefund 是否全额退款
*/
public static function compositeRefundHandle($orderItem, $order, $isFullRefund = false)
{
$snapshoot = $orderItem['snapshoot'];
if (is_string($snapshoot)) {
$snapshoot = json_decode($snapshoot, true);
}
if (empty($snapshoot)) {
return;
}
$subGoodsList = $snapshoot['sub_goods_list'] ?? [];
$userId = $order['user_id'] ?? $order->user_id;
$compositeGoodsId = $orderItem['item_id'];
// 如果全额退款,返还销量
if ($isFullRefund) {
// 组合商品销量 -1
\app\admin\model\app\composite\Goods::where([
'id' => $compositeGoodsId,
'uniacid' => UNIACID
])->setDec('total_sales');
// 子商品销量 -1
foreach ($subGoodsList as $subGoods) {
switch ($subGoods['sub_goods_type']) {
case 'course':
Course::where(['id' => $subGoods['sub_goods_id']])->setDec('sales');
break;
case 'exercises':
\think\Db::name('app_exam_exercises')->where(['id' => $subGoods['sub_goods_id']])->setDec('sales');
break;
case 'audio':
case 'live':
case 'article':
case 'column':
// 音频/直播/图文/专栏统一存储于 tuzhi_course 表,按 id 扣减销量
\think\Db::name('course')->where(['id' => $subGoods['sub_goods_id']])->setDec('sales');
break;
}
}
}
}
}