From 0d3c550f5b7174bec3ed026cfeaea41f1c10693a Mon Sep 17 00:00:00 2001 From: youda Date: Tue, 13 May 2025 16:05:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/Diamond.php | 44 ++++++++++++ app/admin/route/app.php | 2 + app/admin/view/Diamond/index.html | 111 ++++++++++++++++++++---------- app/api/controller/Mall.php | 110 +++++++++++++++++++++++++++++ app/api/controller/Notify.php | 82 ++++++++++++++++++++++ app/api/controller/User.php | 32 ++++++++- app/api/route/app.php | 9 ++- app/common/model/DiamondOrder.php | 82 ++++++++++++++++++++++ 8 files changed, 432 insertions(+), 40 deletions(-) create mode 100644 app/common/model/DiamondOrder.php diff --git a/app/admin/controller/Diamond.php b/app/admin/controller/Diamond.php index 07d6bd2..730db19 100644 --- a/app/admin/controller/Diamond.php +++ b/app/admin/controller/Diamond.php @@ -186,4 +186,48 @@ class Diamond extends Base return $this->err('删除失败'); } } + + /** + * 更改钻石商品状态 + */ + public function status() + { + if (!request()->isPost()) { + return $this->err('请求方式错误'); + } + + $id = input('post.id/d', 0); + $status = input('post.status/d', 0); + + if (!$id) { + return $this->err('参数错误'); + } + + $info = DiamondProducts::getInfo($id); + if (!$info) { + return $this->err('商品不存在'); + } + + // 更新状态 + $result = DiamondProducts::where('id', $id)->update(['status' => $status, 'updated_at' => date('Y-m-d H:i:s')]); + + if ($result) { + return $this->succ('状态更新成功'); + } else { + return $this->err('状态更新失败'); + } + } + + /** + * 获取钻石商品最大排序值 + */ + public function get_max_sort() + { + $maxSort = DiamondProducts::max('sort_order'); + return json([ + 'status' => 1, + 'msg' => '获取成功', + 'data' => intval($maxSort) + ]); + } } \ No newline at end of file diff --git a/app/admin/route/app.php b/app/admin/route/app.php index eea860f..a30b92c 100755 --- a/app/admin/route/app.php +++ b/app/admin/route/app.php @@ -473,4 +473,6 @@ Route::rule('diamond', 'Diamond/index', 'GET|POST'); Route::rule('diamond_add', 'Diamond/add', 'GET|POST'); Route::rule('diamond_edit', 'Diamond/edit', 'GET|POST'); Route::rule('diamond_del', 'Diamond/del', 'GET|POST'); +Route::rule('diamond_status', 'Diamond/status', 'POST'); +Route::rule('diamond_get_max_sort', 'Diamond/get_max_sort', 'GET'); \ No newline at end of file diff --git a/app/admin/view/Diamond/index.html b/app/admin/view/Diamond/index.html index 97d8b95..77851fa 100644 --- a/app/admin/view/Diamond/index.html +++ b/app/admin/view/Diamond/index.html @@ -37,11 +37,7 @@ @@ -127,8 +123,8 @@
- - + +
@@ -162,8 +158,8 @@
- - + +
@@ -199,7 +195,7 @@ { field: 'is_first', title: '是否有首充', width: 100, templet: '#isFirstTpl' }, { field: 'normal_image', title: '展示图', width: 120, templet: '#imageTpl' }, { field: 'sort_order', title: '排序', width: 80 }, - { field: 'status', title: '状态', width: 80, templet: '#statusTpl' }, + { field: 'status', title: '状态', width: 120, templet: '#statusTpl' }, { field: 'created_at', title: '创建时间', width: 160 }, { field: 'updated_at', title: '更新时间', width: 160 }, { fixed: 'right', title: '操作', toolbar: '#toolbarTpl', width: 150 } @@ -230,35 +226,46 @@ var first_bonus_reward_instance = null; // 添加按钮点击事件 $('#addBtn').on('click', function () { - layer.open({ - type: 1, - title: '添加钻石商品', - area: ['900px', '90%'], - content: laytpl($('#formTpl').html()).render({ d: {} }), - success: function (layero, index) { - form.render(); - initUpload(); - // 页面加载时初始化奖励信息区域 - base_reward_instance = initRewardInfo('base_reward_container', null, 'base_reward'); - console.log(base_reward_instance); + // 获取当前最大排序值 + $.get('{:url("/admin/diamond_get_max_sort")}', function(res) { + const maxSort = res.data || 0; + console.log(maxSort); + + layer.open({ + type: 1, + title: '添加钻石商品', + area: ['800px', '90%'], + content: laytpl($('#formTpl').html()).render({ d: {sort_order: maxSort + 1} }), + success: function (layero, index) { + form.render(); + initUpload(); + // 页面加载时初始化奖励信息区域 + base_reward_instance = initRewardInfo('base_reward_container', null, 'base_reward'); + console.log(base_reward_instance); - first_bonus_reward_instance = initRewardInfo('first_bonus_reward_container', null, 'first_bonus_reward'); - - // 监听关闭按钮点击事件 - $('.closeBtn').on('click', function() { - layer.closeAll('page'); - }); - - // 监听是否首充单选框变化 - form.on('radio(is_first)', function (data) { - var value = data.value; - if (value == 1) { - $(data.elem).closest('.layui-form').find('.first-charge-fields').show(); - } else { - $(data.elem).closest('.layui-form').find('.first-charge-fields').hide(); - } - }); - } + first_bonus_reward_instance = initRewardInfo('first_bonus_reward_container', null, 'first_bonus_reward'); + + // 监听关闭按钮点击事件 + $('.closeBtn').on('click', function() { + layer.closeAll('page'); + }); + + // 监听是否首充单选框变化 + form.on('radio(is_first)', function (data) { + var value = data.value; + if (value == 1) { + $(data.elem).closest('.layui-form').find('.first-charge-fields').show(); + } else { + $(data.elem).closest('.layui-form').find('.first-charge-fields').hide(); + } + }); + form.val('diamondForm', {sort_order: maxSort + 1}); + + // 默认显示首充字段 + $('.first-charge-fields').show(); + form.render(); + } + }); }); }); @@ -364,6 +371,34 @@ return false; }); + // 监听状态开关切换 + form.on('switch(statusSwitch)', function(obj){ + var id = this.value; + var status = obj.elem.checked ? 1 : 0; + + $.ajax({ + url: '{:url("/admin/diamond_status")}', + type: 'post', + data: { id: id, status: status }, + success: function(res) { + if (res.status === 1) { + layer.msg(res.msg, { icon: 1, time: 1000 }); + } else { + // 如果修改失败,将开关状态切换回去 + obj.elem.checked = status === 0 ? true : false; + form.render('checkbox'); + layer.msg(res.msg, { icon: 2, time: 1500 }); + } + }, + error: function() { + // 如果请求出错,将开关状态切换回去 + obj.elem.checked = status === 0 ? true : false; + form.render('checkbox'); + layer.msg('操作失败,请重试', { icon: 2, time: 1500 }); + } + }); + }); + // 初始化图片上传 function initUpload() { $('.upload-image').each(function () { diff --git a/app/api/controller/Mall.php b/app/api/controller/Mall.php index d1bbd55..fc92b77 100755 --- a/app/api/controller/Mall.php +++ b/app/api/controller/Mall.php @@ -15,6 +15,8 @@ use app\common\model\Order; use app\common\model\OrderList; use app\common\model\UserVip; use app\common\model\UserCoupon; +use app\common\model\DiamondProducts; +use app\common\model\DiamondOrder; use think\facade\Db; use app\common\model\CouponReceive as CouponReceiveModel; use \think\Request; @@ -868,4 +870,112 @@ class Mall extends Base return $this->renderSuccess('请求成功', $data); } + + public function get_diamond_list() + { + $diamond_list = Db::name('diamond_products')->field('products_id,name,normal_image,normal_select_image,price,status,is_first,first_charge_image,first_select_charge_image') + ->where(['status' => 1]) + ->where('products_type', '=', 1) + ->order('sort_order asc') + ->select()->toArray(); + $user_id = $this->getuserid(); + $diamond_order_count = 0; + if ($user_id > 0) { + $diamond_order_count = DiamondOrder::where('user_id', $user_id) + ->where('status', '=', 'success')->count(); + } + foreach ($diamond_list as &$value) { + //商品有首充,并且用户没有购买记录,才显示首充 + if ($value['is_first'] == 1 && $diamond_order_count == 0) { + $value['image'] = $value['first_charge_image']; + $value['select_image'] = $value['first_select_charge_image']; + } else { + $value['image'] = $value['normal_image']; + $value['select_image'] = $value['normal_select_image']; + } + unset($value['normal_image']); + unset($value['normal_select_image']); + unset($value['first_charge_image']); + unset($value['first_select_charge_image']); + unset($value['is_first']); + } + return $this->renderSuccess('请求成功', $diamond_list); + } + + public function createOrderProducts() + { + $user_id = $this->getuserid(); + if ($user_id == 0) { + return $this->renderError("未登录"); + } + $product_id = request()->param('product_id', ''); + $pay_type = request()->param('pay_type/d', 2); //1.小程序微信支付,2.h5支付宝,3.app微信,4.app支付宝 + $diamond_product = DiamondProducts::where('products_id', '=', $product_id)->find(); + if (!$diamond_product) { + return $this->renderError("商品不存在"); + } + if ($diamond_product['status'] != 1) { + return $this->renderError("商品已下架"); + } + + $redis = (new \app\common\server\RedisHelper())->getRedis(); + $redis_key = "kpw_products" . '_' . $user_id; + $redis_key_info = $redis->get($redis_key); + if ($redis_key_info) { + return $this->renderError("当前操作太快了,请等待"); + } else { + $redis->set($redis_key, 1, 10); + } + + // 查询用户钻石订单数,判断是否首充 + $diamond_order_count = DiamondOrder::where('user_id', $user_id) + ->where('status', '=', DiamondOrder::STATUS_SUCCESS)->count(); + + Db::startTrans(); + try { + $user = $this->getUser(); + $attach = 'order_product'; + $title = '购买钻石' . $diamond_product['name']; + $price = $diamond_product['price']; + $payRes = \app\common\server\platform\PlatformFactory::createPay($user, $diamond_product['price'], $title, $attach, "ZS_"); + if ($payRes['status'] !== 1) { + throw new \Exception(isset($payRes['msg']) ? $payRes['msg'] : "购买失败,请刷新重试"); + } + $order_num = $payRes['data']['order_no']; + + // 创建钻石订单 + $order_id = DiamondOrder::insertGetId([ + 'order_no' => $order_num, + 'user_id' => $user['id'], + 'diamond_id' => $diamond_product['id'], + 'product_id' => $product_id, + 'amount_paid' => $price, + 'pay_method' => $pay_type == 1 || $pay_type == 3 ? DiamondOrder::PAY_METHOD_WECHAT : DiamondOrder::PAY_METHOD_ALIPAY, + 'is_first_charge' => $diamond_order_count == 0 ? 1 : 0, + 'status' => DiamondOrder::STATUS_PENDING, + 'created_at' => date('Y-m-d H:i:s') + ]); + + if (!$order_id) { + throw new \Exception("订单创建失败"); + } + + Db::commit(); + + // 删除redis锁 + $redis->del($redis_key); + + return $this->renderSuccess("下单成功", [ + 'status' => 1, + 'order_num' => $order_num, + 'res' => $payRes['data']['res'], + ]); + + } catch (\Exception $e) { + Db::rollback(); + // 删除redis锁 + $redis->del($redis_key); + return $this->renderError($e->getMessage()); + } + } } diff --git a/app/api/controller/Notify.php b/app/api/controller/Notify.php index fbf65d3..e1ee53f 100755 --- a/app/api/controller/Notify.php +++ b/app/api/controller/Notify.php @@ -2819,6 +2819,81 @@ class Notify extends Base $this->wx_gf_fahuo($user_id, $order_num); } + } elseif ($order_type == 'order_product') { + // 钻石订单处理逻辑 + $diamondOrder = \app\common\model\DiamondOrder::where('order_no', '=', $order_num) + ->where('status', '=', \app\common\model\DiamondOrder::STATUS_PENDING) + ->find(); + + if (!$diamondOrder) { + writelog('pay_notify_error', "未找到钻石订单或状态错误: " . $order_num); + \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '未找到钻石订单或状态错误'); + Db::rollback(); + $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 + return; + } + + // 验证用户ID是否一致 + if ($diamondOrder['user_id'] != $user_id) { + writelog('pay_notify_error', "用户ID不匹配: 通知中的用户ID={$user_id}, 钻石订单中的用户ID={$diamondOrder['user_id']}"); + \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '用户ID不匹配'); + Db::rollback(); + $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 + return; + } + + $price = $diamondOrder['amount_paid']; + + // 查询钻石商品信息 + $diamondProduct = \app\common\model\DiamondProducts::where('id', '=', $diamondOrder['diamond_id'])->find(); + if (!$diamondProduct) { + writelog('pay_notify_error', "未找到钻石商品: " . $diamondOrder['diamond_id']); + \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '未找到钻石商品'); + Db::rollback(); + $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 + return; + } + + $reward_log = ''; + + if ($diamondProduct['base_reward'] == "") { + writelog('pay_notify_error', "商品没有设置基础奖励: " . $diamondOrder['diamond_id']); + \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '商品没有设置基础奖励'); + Db::rollback(); + $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 + return; + } + // 给用户钱包加钻石 + $reward_res = RewardService::sendReward($user_id, $diamondProduct['base_reward'], '购买商品' . $diamondProduct['name']); + if ($reward_res) { + $reward_log = '购买商品' . implode(',', $reward_res['data']); + } + //判断商品是否开启首充 + if ($diamondProduct['is_first'] == 1) { + //判断是否有首充 + $diamond_order_count = \app\common\model\DiamondOrder::where('user_id', $user_id) + ->where('status', '=', 'success')->count(); + if ($diamond_order_count == 0 && $diamondProduct['first_bonus_reward'] != '') { + $reward_res = RewardService::sendReward($user_id, $diamondProduct['first_bonus_reward'], '首充赠送'); + $reward_log = '首充赠送' . implode(',', $reward_res['data']); + + } + } + // 更新订单状态为支付成功 + $res[] = $diamondOrder->save([ + 'status' => \app\common\model\DiamondOrder::STATUS_SUCCESS, + 'paid_at' => date('Y-m-d H:i:s'), + 'reward_log' => '支付成功,' . $reward_log + ]); + // 记录支付信息 + $res[] = Db::name('profit_pay')->insert([ + 'user_id' => $user_id, + 'order_num' => $order_num, + 'change_money' => $price, + 'content' => '购买钻石' . $diamondProduct['name'], + 'pay_type' => $payment_type == 'alipay' ? 2 : 1, + 'addtime' => time(), + ]); } else { // 普通盒子订单处理逻辑 $orderInfo = Order::where('order_num', '=', $order_num) @@ -2905,6 +2980,13 @@ class Notify extends Base // 标记订单为卡单状态 if ($order_type == 'order_list_send') { OrderListSend::where(['send_num' => $order_num])->update(['kd_is' => 1]); + } elseif ($order_type == 'order_product') { + // 钻石订单处理异常,标记为失败状态 + \app\common\model\DiamondOrder::where(['order_no' => $order_num]) + ->update([ + 'status' => \app\common\model\DiamondOrder::STATUS_FAILED, + 'reward_log' => '支付处理异常: ' . $e->getMessage() + ]); } else { Order::where(['order_num' => $order_num])->update(['kd_is' => 1]); } diff --git a/app/api/controller/User.php b/app/api/controller/User.php index f8ada5c..9115c28 100755 --- a/app/api/controller/User.php +++ b/app/api/controller/User.php @@ -1254,5 +1254,35 @@ class User extends Base } } - + + + /** + * 我的 + */ + public function userInfo(Request $request) + { + $user_id = $this->getuserid(); + if ($user_id == 0) { + return $this->renderError("未登录"); + } + $user = Usermodel::where('id', '=', $user_id)->find(); + if (!$user) { + return $this->renderError("用户不存在"); + } + $userinfo['id'] = $user['id']; + $userinfo['ID'] = $user['id']; + $userinfo['mobile_is'] = $user['mobile'] ? 1 : 0; + $userinfo['nickname'] = $user['nickname']; + $userinfo['headimg'] = imageUrl($user['headimg']); + $userinfo['mobile'] = $user['mobile'] ? substr_replace($user['mobile'], '****', 3, 4) : ''; + $userinfo['money'] = $user['money'];//钻石 + $userinfo['money2'] = $user['money2'];//达达券 + $userinfo['integral'] = $user['integral'];//UU币 + $userinfo['uid'] = $user['uid'] ? $user['uid'] : $user['id']; + $day = floor(abs(time() - $user['addtime']) / 86400); + $userinfo['day'] = $day; + return $this->renderSuccess("请求成功", $userinfo); + } + + } \ No newline at end of file diff --git a/app/api/route/app.php b/app/api/route/app.php index 8e9a3d5..a94ff46 100755 --- a/app/api/route/app.php +++ b/app/api/route/app.php @@ -47,6 +47,7 @@ Route::any('getDanye', 'Index/getDanye'); #User.php个人中心 #============================ Route::any('user', 'User/user'); +Route::any('userInfo', 'User/userInfo'); Route::any('update_userinfo', 'User/update_userinfo'); Route::any('vip_list', 'User/vip_list'); Route::any('profitIntegral', 'User/profitIntegral'); @@ -235,4 +236,10 @@ Route::any('getAddressList', 'Other/getAddressList'); Route::any('deleteAddress', 'Other/deleteAddress'); Route::any('setDefaultAddress', 'Other/setDefaultAddress'); Route::any('getAddressDetail', 'Other/getAddressDetail'); -#=============用户地址管理============= \ No newline at end of file +#=============用户地址管理============= + +#============================ +# 钻石管理 +#============================ +Route::any('get_diamond_list', 'Mall/get_diamond_list'); +Route::any('createOrderProducts', 'Mall/createOrderProducts'); \ No newline at end of file diff --git a/app/common/model/DiamondOrder.php b/app/common/model/DiamondOrder.php new file mode 100644 index 0000000..cb82d1c --- /dev/null +++ b/app/common/model/DiamondOrder.php @@ -0,0 +1,82 @@ + 'integer', + 'user_id' => 'integer', + 'diamond_id' => 'integer', + 'amount_paid' => 'float', + 'is_first_charge' => 'boolean', + ]; + + // 设置只读字段 + protected $readonly = ['order_no']; + + // 订单状态常量 + const STATUS_PENDING = 'pending'; + const STATUS_SUCCESS = 'success'; + const STATUS_FAILED = 'failed'; + + // 支付方式常量 + const PAY_METHOD_ALIPAY = 'alipay'; + const PAY_METHOD_WECHAT = 'wechat'; + + /** + * 关联用户 + */ + public function user() + { + return $this->belongsTo('User', 'user_id'); + } + + /** + * 获取订单状态列表 + */ + public static function getStatusList() + { + return [ + self::STATUS_PENDING => '待支付', + self::STATUS_SUCCESS => '支付成功', + self::STATUS_FAILED => '支付失败' + ]; + } + + /** + * 获取支付方式列表 + */ + public static function getPayMethodList() + { + return [ + self::PAY_METHOD_ALIPAY => '支付宝', + self::PAY_METHOD_WECHAT => '微信支付' + ]; + } + + /** + * 生成唯一订单号 + */ + public static function generateOrderNo() + { + return date('YmdHis') . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8); + } +} \ No newline at end of file