Browse Source

Fix 优惠券在特殊情况下条件未检查

兔姬桑 3 years ago
parent
commit
eacf63747d

+ 7 - 6
app/Http/Controllers/Admin/CouponController.php

@@ -35,12 +35,6 @@ class CouponController extends Controller
         return view('admin.coupon.index', ['couponList' => $query->latest()->paginate(15)->appends($request->except('page'))]);
     }
 
-    // 添加优惠券页面
-    public function create()
-    {
-        return view('admin.coupon.create');
-    }
-
     // 添加优惠券
     public function store(CouponRequest $request)
     {
@@ -57,6 +51,7 @@ class CouponController extends Controller
         $num = (int) $request->input('num');
         $data = $request->only(['name', 'type', 'usable_times', 'value', 'rule', 'start_time', 'end_time']);
         $data['logo'] = $logo;
+        $data['status'] = 0;
         try {
             for ($i = 0; $i < $num; $i++) {
                 $data['sn'] = $num === 1 && $request->input('sn') ? $request->input('sn') : Str::random(8);
@@ -71,6 +66,12 @@ class CouponController extends Controller
         }
     }
 
+    // 添加优惠券页面
+    public function create()
+    {
+        return view('admin.coupon.create');
+    }
+
     // 删除优惠券
     public function destroy(Coupon $coupon): JsonResponse
     {

+ 53 - 8
app/Http/Controllers/PaymentController.php

@@ -87,8 +87,7 @@ class PaymentController extends Controller
         return Response::json(['status' => 'error', 'message' => '未知订单']);
     }
 
-    // 创建支付订单
-    public function purchase(Request $request)
+    public function purchase(Request $request) // 创建支付订单
     {
         $goods_id = $request->input('goods_id');
         $coupon_sn = $request->input('coupon_sn');
@@ -128,11 +127,14 @@ class PaymentController extends Controller
 
             // 使用优惠券
             if ($coupon_sn) {
-                $coupon = Coupon::whereStatus(0)->whereIn('type', [1, 2])->whereSn($coupon_sn)->first();
-                if (! $coupon) {
-                    return Response::json(['status' => 'fail', 'message' => '订单创建失败:优惠券不存在']);
+                $ret = $this->couponCheck($coupon_sn, $goods->price);
+
+                if ($ret !== true) {
+                    return $ret;
                 }
 
+                $coupon = Coupon::whereStatus(0)->whereIn('type', [1, 2])->whereSn($coupon_sn)->firstOrFail();
+
                 // 计算实际应支付总价
                 $amount = $coupon->type === 2 ? $goods->price * $coupon->value / 100 : $goods->price - $coupon->value;
                 $amount = $amount > 0 ? round($amount, 2) : 0; // 四舍五入保留2位小数,避免无法正常创建订单
@@ -179,7 +181,7 @@ class PaymentController extends Controller
             // 使用优惠券,减少可使用次数
             if (! empty($coupon)) {
                 if ($coupon->usable_times > 0) {
-                    $coupon->decrement('usable_times', 1);
+                    $coupon->decrement('usable_times');
                 }
 
                 Helpers::addCouponLog('订单支付使用', $coupon->id, $goods_id, $newOrder->id);
@@ -196,6 +198,50 @@ class PaymentController extends Controller
         return Response::json(['status' => 'fail', 'message' => '订单创建失败']);
     }
 
+    public function couponCheck($coupon_sn, $price) // 检查券合规性
+    {
+        if (empty($coupon_sn)) {
+            return Response::json([
+                'status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('validation.required', ['attribute' => trans('user.coupon.attribute')]),
+            ]);
+        }
+
+        $coupon = Coupon::whereSn($coupon_sn)->whereIn('type', [1, 2])->first();
+        if (! $coupon) {
+            return Response::json(['status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('user.coupon.error.unknown')]);
+        }
+
+        if ($coupon->status === 1) {
+            return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.used')]);
+        }
+        if ($coupon->getRawOriginal('end_time') < time()) {
+            $coupon->status = 2;
+            $coupon->save();
+
+            return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.expired')]);
+        }
+
+        if ($coupon->status === 2) {
+            if ($coupon->usable_times === 0) {
+                return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.run_out')]);
+            }
+
+            return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.expired')]);
+        }
+
+        if ($coupon->start_time > date('Y-m-d H:i:s')) {
+            return Response::json(['status'  => 'fail', 'title' => trans('user.coupon.error.inactive'),
+                'message' => trans('user.coupon.error.wait', ['time' => $coupon->start_time]),
+            ]);
+        }
+
+        if ($price < $coupon->rule) {
+            return Response::json(['status' => 'fail', 'title' => trans('user.coupon.error.limit'), 'message' => trans('user.coupon.error.higher', ['amount' => $coupon->rule])]);
+        }
+
+        return true;
+    }
+
     public function close(Order $order): JsonResponse
     {
         if (! $order->close()) {
@@ -205,8 +251,7 @@ class PaymentController extends Controller
         return Response::json(['status' => 'success', 'message' => '关闭订单成功']);
     }
 
-    // 支付单详情
-    public function detail($trade_no)
+    public function detail($trade_no) // 支付单详情
     {
         $payment = Payment::uid()->with(['order', 'order.goods'])->whereTradeNo($trade_no)->firstOrFail();
         $goods = $payment->order->goods;

+ 5 - 38
app/Http/Controllers/UserController.php

@@ -403,46 +403,13 @@ class UserController extends Controller
     public function redeemCoupon(Request $request): JsonResponse
     {
         $coupon_sn = $request->input('coupon_sn');
-        $good_price = $request->input('price');
 
-        if (empty($coupon_sn)) {
-            return Response::json([
-                'status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('validation.required', ['attribute' => trans('user.coupon.attribute')]),
-            ]);
-        }
-
-        $coupon = Coupon::whereSn($coupon_sn)->whereIn('type', [1, 2])->first();
-        if (! $coupon) {
-            return Response::json(['status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('user.coupon.error.unknown')]);
-        }
-
-        if ($coupon->status === 1) {
-            return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.used')]);
-        }
-        if ($coupon->getRawOriginal('end_time') < time()) {
-            $coupon->status = 2;
-            $coupon->save();
-
-            return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.expired')]);
-        }
-
-        if ($coupon->status === 2) {
-            if ($coupon->usable_times === 0) {
-                return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.run_out')]);
-            }
-
-            return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.expired')]);
-        }
-
-        if ($coupon->start_time > date('Y-m-d H:i:s')) {
-            return Response::json(['status'  => 'fail', 'title' => trans('user.coupon.error.inactive'),
-                'message' => trans('user.coupon.error.wait', ['time' => $coupon->start_time]),
-            ]);
-        }
+        $ret = (new PaymentController())->couponCheck($coupon_sn, $request->input('price'));
 
-        if ($good_price < $coupon->rule) {
-            return Response::json(['status' => 'fail', 'title' => trans('user.coupon.error.limit'), 'message' => trans('user.coupon.error.higher', ['amount' => $coupon->rule])]);
+        if ($ret !== true) {
+            return $ret;
         }
+        $coupon = Coupon::whereSn($coupon_sn)->whereIn('type', [1, 2])->firstOrFail();
 
         $data = [
             'name'  => $coupon->name,
@@ -501,7 +468,7 @@ class UserController extends Controller
             'Shadowrocket_linkQrcode' => 'sub://'.base64url_encode($subscribe_link).'#'.base64url_encode(sysConfig('website_name')),
             'Clash_link'              => "clash://install-config?url={$subscribe_link}",
             'Surge_link'              => "surge:///install-config?url={$subscribe_link}",
-            'QuantumultX_link'             => 'quantumult-x:///update-configuration?remote-resource='.json_encode([
+            'QuantumultX_link'        => 'quantumult-x:///update-configuration?remote-resource='.json_encode([
                 'server_remote'  => ["{$subscribe_link}, tag=".sysConfig('website_name')],
                 'filter_remote'  => [],
                 'rewrite_remote' => [],