mirror of
				https://github.com/v2board/v2board.git
				synced 2025-10-31 17:31:49 +08:00 
			
		
		
		
	update
This commit is contained in:
		
							
								
								
									
										33
									
								
								app/Http/Controllers/User/CouponController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/Http/Controllers/User/CouponController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Models\Coupon; | ||||
|  | ||||
| class CouponController extends Controller | ||||
| { | ||||
|     public function check(Request $request) | ||||
|     { | ||||
|         if (empty($request->input('code'))) { | ||||
|             abort(500, '优惠券码不能为空'); | ||||
|         } | ||||
|         $coupon = Coupon::where('code', $request->input('code'))->first(); | ||||
|         if (!$coupon) { | ||||
|             abort(500, '优惠券无效'); | ||||
|         } | ||||
|         if ($coupon->limit_use <= 0 && $coupon->limit_use !== NULL) { | ||||
|             abort(500, '优惠券已无可用次数'); | ||||
|         } | ||||
|         if (time() < $coupon->started_at) { | ||||
|             abort(500, '优惠券还未到可用时间'); | ||||
|         } | ||||
|         if (time() > $coupon->ended_at) { | ||||
|             abort(500, '优惠券已过期'); | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => $coupon | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										76
									
								
								app/Http/Controllers/User/InviteController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								app/Http/Controllers/User/InviteController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Models\User; | ||||
| use App\Models\Order; | ||||
| use App\Models\InviteCode; | ||||
| use App\Utils\Helper; | ||||
|  | ||||
| class InviteController extends Controller | ||||
| { | ||||
|     public function save(Request $request) | ||||
|     { | ||||
|         if (InviteCode::where('user_id', $request->session()->get('id'))->where('status', 0)->count() >= config('v2board.invite_gen_limit', 5)) { | ||||
|             abort(500, '已达到创建数量上限'); | ||||
|         } | ||||
|         $inviteCode = new InviteCode(); | ||||
|         $inviteCode->user_id = $request->session()->get('id'); | ||||
|         $inviteCode->code = Helper::randomChar(8); | ||||
|         return response([ | ||||
|             'data' => $inviteCode->save() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function details(Request $request) | ||||
|     { | ||||
|         return response([ | ||||
|             'data' => Order::where('invite_user_id', $request->session()->get('id')) | ||||
|                 ->where('status', 3) | ||||
|                 ->select([ | ||||
|                     'id', | ||||
|                     'commission_status', | ||||
|                     'commission_balance', | ||||
|                     'created_at', | ||||
|                     'updated_at' | ||||
|                 ]) | ||||
|                 ->get() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function fetch(Request $request) | ||||
|     { | ||||
|         $codes = InviteCode::where('user_id', $request->session()->get('id')) | ||||
|             ->where('status', 0) | ||||
|             ->get(); | ||||
|         $commission_rate = config('v2board.invite_commission'); | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         if ($user->commission_rate) { | ||||
|             $commission_rate = $user->commission_rate; | ||||
|         } | ||||
|         $stat = [ | ||||
|             //已注册用户数 | ||||
|             (int)User::where('invite_user_id', $request->session()->get('id'))->count(), | ||||
|             //有效的佣金 | ||||
|             (int)Order::where('status', 3) | ||||
|                 ->where('commission_status', 1) | ||||
|                 ->where('invite_user_id', $request->session()->get('id')) | ||||
|                 ->sum('commission_balance'), | ||||
|             //确认中的佣金 | ||||
|             (int)Order::where('status', 3) | ||||
|                 ->where('commission_status', 0) | ||||
|                 ->where('invite_user_id', $request->session()->get('id')) | ||||
|                 ->sum('commission_balance'), | ||||
|             //佣金比例 | ||||
|             (int)$commission_rate | ||||
|         ]; | ||||
|         return response([ | ||||
|             'data' => [ | ||||
|                 'codes' => $codes, | ||||
|                 'stat' => $stat | ||||
|             ] | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								app/Http/Controllers/User/NoticeController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								app/Http/Controllers/User/NoticeController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Models\Notice; | ||||
| use App\Utils\Helper; | ||||
|  | ||||
| class NoticeController extends Controller | ||||
| { | ||||
|     public function fetch(Request $request) | ||||
|     { | ||||
|         return response([ | ||||
|             'data' => Notice::orderBy('created_at', 'DESC')->first() | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										430
									
								
								app/Http/Controllers/User/OrderController.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										430
									
								
								app/Http/Controllers/User/OrderController.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,430 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use App\Http\Requests\OrderSave; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Cache; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use App\Models\Order; | ||||
| use App\Models\Plan; | ||||
| use App\Models\User; | ||||
| use App\Models\Coupon; | ||||
| use App\Utils\Helper; | ||||
| use Omnipay\Omnipay; | ||||
| use Stripe\Stripe; | ||||
| use Stripe\Source; | ||||
| use Library\BitpayX; | ||||
| use Library\PayTaro; | ||||
|  | ||||
| class OrderController extends Controller | ||||
| { | ||||
|     public function fetch(Request $request) | ||||
|     { | ||||
|         $model = Order::where('user_id', $request->session()->get('id')) | ||||
|             ->orderBy('created_at', 'DESC'); | ||||
|         if ($request->input('status') !== null) { | ||||
|             $model->where('status', $request->input('status')); | ||||
|         } | ||||
|         $order = $model->get(); | ||||
|         $plan = Plan::get(); | ||||
|         for ($i = 0; $i < count($order); $i++) { | ||||
|             for ($x = 0; $x < count($plan); $x++) { | ||||
|                 if ($order[$i]['plan_id'] === $plan[$x]['id']) { | ||||
|                     $order[$i]['plan'] = $plan[$x]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => $order | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function details(Request $request) | ||||
|     { | ||||
|         $order = Order::where('user_id', $request->session()->get('id')) | ||||
|             ->where('trade_no', $request->input('trade_no')) | ||||
|             ->first(); | ||||
|         if (!$order) { | ||||
|             abort(500, '订单不存在'); | ||||
|         } | ||||
|         $order['plan'] = Plan::find($order->plan_id); | ||||
|         $order['plan_transfer_hour'] = config('v2board.plan_transfer_hour', 12); | ||||
|         $order['try_out_plan_id'] = (int)config('v2board.try_out_plan_id'); | ||||
|         if (!$order['plan']) { | ||||
|             abort(500, '订阅不存在'); | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => $order | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     private function isExistNotPayOrderByUserId($userId) | ||||
|     { | ||||
|         $order = Order::where('status', 0) | ||||
|             ->where('user_id', $userId) | ||||
|             ->first(); | ||||
|         if (!$order) { | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public function save(OrderSave $request) | ||||
|     { | ||||
|         if ($this->isExistNotPayOrderByUserId($request->session()->get('id'))) { | ||||
|             abort(500, '存在未付款订单,请取消后再试'); | ||||
|         } | ||||
|  | ||||
|         $plan = Plan::find($request->input('plan_id')); | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|  | ||||
|         if (!$plan) { | ||||
|             abort(500, '该订阅不存在'); | ||||
|         } | ||||
|  | ||||
|         if (!($plan->show || $user->plan_id == $plan->id)) { | ||||
|             abort(500, '该订阅已售罄'); | ||||
|         } | ||||
|  | ||||
|         if (!$plan->show && !$plan->renew) { | ||||
|             abort(500, '该订阅无法续费,请更换其他订阅'); | ||||
|         } | ||||
|  | ||||
|         if ($plan[$request->input('cycle')] === NULL) { | ||||
|             abort(500, '该订阅周期无法进行购买,请选择其他周期'); | ||||
|         } | ||||
|  | ||||
|         if ($request->input('coupon_code')) { | ||||
|             $coupon = Coupon::where('code', $request->input('coupon_code'))->first(); | ||||
|             if (!$coupon) { | ||||
|                 abort(500, '优惠券无效'); | ||||
|             } | ||||
|             if ($coupon->limit_use <= 0 && $coupon->limit_use !== NULL) { | ||||
|                 abort(500, '优惠券已无可用次数'); | ||||
|             } | ||||
|             if (time() < $coupon->started_at) { | ||||
|                 abort(500, '优惠券还未到可用时间'); | ||||
|             } | ||||
|             if (time() > $coupon->ended_at) { | ||||
|                 abort(500, '优惠券已过期'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         DB::beginTransaction(); | ||||
|         $order = new Order(); | ||||
|         $order->user_id = $request->session()->get('id'); | ||||
|         $order->plan_id = $plan->id; | ||||
|         $order->cycle = $request->input('cycle'); | ||||
|         $order->trade_no = Helper::guid(); | ||||
|         $order->total_amount = $plan[$request->input('cycle')]; | ||||
|         // renew and change subscribe process | ||||
|         if ($user->expired_at > time() && $order->plan_id !== $user->plan_id) { | ||||
|             $order->type = 3; | ||||
|             if (!(int)config('v2board.plan_change_enable', 1)) abort(500, '目前不允许更改订阅,请联系管理员'); | ||||
|         } else if ($user->expired_at > time() && $order->plan_id == $user->plan_id) { | ||||
|             $order->type = 2; | ||||
|         } else { | ||||
|             $order->type = 1; | ||||
|         } | ||||
|         // coupon process | ||||
|         if (isset($coupon)) { | ||||
|             switch ($coupon->type) { | ||||
|                 case 1: | ||||
|                     $order->discount_amount = $coupon->value; | ||||
|                     break; | ||||
|                 case 2: | ||||
|                     $order->discount_amount = $order->total_amount * ($coupon->value / 100); | ||||
|                     break; | ||||
|             } | ||||
|             $order->total_amount = $order->total_amount - $order->discount_amount; | ||||
|             if ($coupon->limit_use !== NULL) { | ||||
|                 $coupon->limit_use = $coupon->limit_use - 1; | ||||
|                 if (!$coupon->save()) { | ||||
|                     DB::rollback(); | ||||
|                     abort(500, '优惠券使用失败'); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // free process | ||||
|         if ($order->total_amount <= 0) { | ||||
|             $order->total_amount = 0; | ||||
|             $order->status = 1; | ||||
|         } | ||||
|         // invite process | ||||
|         if ($user->invite_user_id && $order->total_amount > 0) { | ||||
|             $order->invite_user_id = $user->invite_user_id; | ||||
|             $inviter = User::find($user->invite_user_id); | ||||
|             if ($inviter && $inviter->commission_rate) { | ||||
|                 $order->commission_balance = $order->total_amount * ($inviter->commission_rate / 100); | ||||
|             } else { | ||||
|                 $order->commission_balance = $order->total_amount * (config('v2board.invite_commission', 10) / 100); | ||||
|             } | ||||
|         } | ||||
|         if (!$order->save()) { | ||||
|             DB::rollback(); | ||||
|             abort(500, '订单创建失败'); | ||||
|         } | ||||
|  | ||||
|         DB::commit(); | ||||
|  | ||||
|         return response([ | ||||
|             'data' => $order->trade_no | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function checkout(Request $request) | ||||
|     { | ||||
|         $tradeNo = $request->input('trade_no'); | ||||
|         $method = $request->input('method'); | ||||
|         $order = Order::where('trade_no', $tradeNo) | ||||
|             ->where('user_id', $request->session()->get('id')) | ||||
|             ->where('status', 0) | ||||
|             ->first(); | ||||
|         if (!$order) { | ||||
|             abort(500, '订单不存在或已支付'); | ||||
|         } | ||||
|         switch ($method) { | ||||
|             // return type => 0: QRCode / 1: URL | ||||
|             case 0: | ||||
|                 // alipayF2F | ||||
|                 if (!(int)config('v2board.alipay_enable')) { | ||||
|                     abort(500, '支付方式不可用'); | ||||
|                 } | ||||
|                 return response([ | ||||
|                     'type' => 0, | ||||
|                     'data' => $this->alipayF2F($tradeNo, $order->total_amount) | ||||
|                 ]); | ||||
|             case 2: | ||||
|                 // stripeAlipay | ||||
|                 if (!(int)config('v2board.stripe_alipay_enable')) { | ||||
|                     abort(500, '支付方式不可用'); | ||||
|                 } | ||||
|                 return response([ | ||||
|                     'type' => 1, | ||||
|                     'data' => $this->stripeAlipay($order) | ||||
|                 ]); | ||||
|             case 3: | ||||
|                 // stripeWepay | ||||
|                 if (!(int)config('v2board.stripe_wepay_enable')) { | ||||
|                     abort(500, '支付方式不可用'); | ||||
|                 } | ||||
|                 return response([ | ||||
|                     'type' => 0, | ||||
|                     'data' => $this->stripeWepay($order) | ||||
|                 ]); | ||||
|             case 4: | ||||
|                 // bitpayX | ||||
|                 if (!(int)config('v2board.bitpayx_enable')) { | ||||
|                     abort(500, '支付方式不可用'); | ||||
|                 } | ||||
|                 return response([ | ||||
|                     'type' => 1, | ||||
|                     'data' => $this->bitpayX($order) | ||||
|                 ]); | ||||
|             case 5: | ||||
|                 if (!(int)config('v2board.paytaro_enable')) { | ||||
|                     abort(500, '支付方式不可用'); | ||||
|                 } | ||||
|                 return response([ | ||||
|                     'type' => 1, | ||||
|                     'data' => $this->payTaro($order) | ||||
|                 ]); | ||||
|             default: | ||||
|                 abort(500, '支付方式不存在'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function check(Request $request) | ||||
|     { | ||||
|         $tradeNo = $request->input('trade_no'); | ||||
|         $order = Order::where('trade_no', $tradeNo) | ||||
|             ->where('user_id', $request->session()->get('id')) | ||||
|             ->first(); | ||||
|         if (!$order) { | ||||
|             abort(500, '订单不存在'); | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => $order->status | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getPaymentMethod() | ||||
|     { | ||||
|         $data = []; | ||||
|         if ((int)config('v2board.alipay_enable')) { | ||||
|             $alipayF2F = new \StdClass(); | ||||
|             $alipayF2F->name = '支付宝'; | ||||
|             $alipayF2F->method = 0; | ||||
|             $alipayF2F->icon = 'alipay'; | ||||
|             array_push($data, $alipayF2F); | ||||
|         } | ||||
|  | ||||
|         if ((int)config('v2board.stripe_alipay_enable')) { | ||||
|             $stripeAlipay = new \StdClass(); | ||||
|             $stripeAlipay->name = '支付宝'; | ||||
|             $stripeAlipay->method = 2; | ||||
|             $stripeAlipay->icon = 'alipay'; | ||||
|             array_push($data, $stripeAlipay); | ||||
|         } | ||||
|  | ||||
|         if ((int)config('v2board.stripe_wepay_enable')) { | ||||
|             $stripeWepay = new \StdClass(); | ||||
|             $stripeWepay->name = '微信'; | ||||
|             $stripeWepay->method = 3; | ||||
|             $stripeWepay->icon = 'wechat'; | ||||
|             array_push($data, $stripeWepay); | ||||
|         } | ||||
|  | ||||
|         if ((int)config('v2board.bitpayx_enable')) { | ||||
|             $bitpayX = new \StdClass(); | ||||
|             $bitpayX->name = '聚合支付'; | ||||
|             $bitpayX->method = 4; | ||||
|             $bitpayX->icon = 'wallet'; | ||||
|             array_push($data, $bitpayX); | ||||
|         } | ||||
|  | ||||
|         if ((int)config('v2board.paytaro_enable')) { | ||||
|             $obj = new \StdClass(); | ||||
|             $obj->name = '聚合支付'; | ||||
|             $obj->method = 5; | ||||
|             $obj->icon = 'wallet'; | ||||
|             array_push($data, $obj); | ||||
|         } | ||||
|  | ||||
|         return response([ | ||||
|             'data' => $data | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function cancel(Request $request) | ||||
|     { | ||||
|         if (empty($request->input('trade_no'))) { | ||||
|             abort(500, '参数有误'); | ||||
|         } | ||||
|         $order = Order::where('trade_no', $request->input('trade_no')) | ||||
|             ->where('user_id', $request->session()->get('id')) | ||||
|             ->first(); | ||||
|         if (!$order) { | ||||
|             abort(500, '订单不存在'); | ||||
|         } | ||||
|         if ($order->status !== 0) { | ||||
|             abort(500, '只可以取消待支付订单'); | ||||
|         } | ||||
|         $order->status = 2; | ||||
|         if (!$order->save()) { | ||||
|             abort(500, '取消失败'); | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     private function alipayF2F($tradeNo, $totalAmount) | ||||
|     { | ||||
|         $gateway = Omnipay::create('Alipay_AopF2F'); | ||||
|         $gateway->setSignType('RSA2'); //RSA/RSA2 | ||||
|         $gateway->setAppId(config('v2board.alipay_appid')); | ||||
|         $gateway->setPrivateKey(config('v2board.alipay_privkey')); // 可以是路径,也可以是密钥内容 | ||||
|         $gateway->setAlipayPublicKey(config('v2board.alipay_pubkey')); // 可以是路径,也可以是密钥内容 | ||||
|         $gateway->setNotifyUrl(url('/api/v1/guest/order/alipayNotify')); | ||||
|         $request = $gateway->purchase(); | ||||
|         $request->setBizContent([ | ||||
|             'subject' => config('v2board.app_name', 'V2Board') . ' - 订阅', | ||||
|             'out_trade_no' => $tradeNo, | ||||
|             'total_amount' => $totalAmount / 100 | ||||
|         ]); | ||||
|         /** @var \Omnipay\Alipay\Responses\AopTradePreCreateResponse $response */ | ||||
|         $response = $request->send(); | ||||
|         $result = $response->getAlipayResponse(); | ||||
|         if ($result['code'] !== '10000') { | ||||
|             abort(500, $result['sub_msg']); | ||||
|         } | ||||
|         // 获取收款二维码内容 | ||||
|         return $response->getQrCode(); | ||||
|     } | ||||
|  | ||||
|     private function stripeAlipay($order) | ||||
|     { | ||||
|         $exchange = Helper::exchange('CNY', 'HKD'); | ||||
|         if (!$exchange) { | ||||
|             abort(500, '货币转换超时,请稍后再试'); | ||||
|         } | ||||
|         Stripe::setApiKey(config('v2board.stripe_sk_live')); | ||||
|         $source = Source::create([ | ||||
|             'amount' => floor($order->total_amount * $exchange), | ||||
|             'currency' => 'hkd', | ||||
|             'type' => 'alipay', | ||||
|             'redirect' => [ | ||||
|                 'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order' | ||||
|             ] | ||||
|         ]); | ||||
|         if (!$source['redirect']['url']) { | ||||
|             abort(500, '支付网关请求失败'); | ||||
|         } | ||||
|  | ||||
|         if (!Cache::put($source['id'], $order->trade_no, 3600)) { | ||||
|             abort(500, '订单创建失败'); | ||||
|         } | ||||
|         return $source['redirect']['url']; | ||||
|     } | ||||
|  | ||||
|     private function stripeWepay($order) | ||||
|     { | ||||
|         $exchange = Helper::exchange('CNY', 'HKD'); | ||||
|         if (!$exchange) { | ||||
|             abort(500, '货币转换超时,请稍后再试'); | ||||
|         } | ||||
|         Stripe::setApiKey(config('v2board.stripe_sk_live')); | ||||
|         $source = Source::create([ | ||||
|             'amount' => floor($order->total_amount * $exchange), | ||||
|             'currency' => 'hkd', | ||||
|             'type' => 'wechat', | ||||
|             'redirect' => [ | ||||
|                 'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order' | ||||
|             ] | ||||
|         ]); | ||||
|         if (!$source['wechat']['qr_code_url']) { | ||||
|             abort(500, '支付网关请求失败'); | ||||
|         } | ||||
|         if (!Cache::put($source['id'], $order->trade_no, 3600)) { | ||||
|             abort(500, '订单创建失败'); | ||||
|         } | ||||
|         return $source['wechat']['qr_code_url']; | ||||
|     } | ||||
|  | ||||
|     private function bitpayX($order) | ||||
|     { | ||||
|         $bitpayX = new BitpayX(config('v2board.bitpayx_appsecret')); | ||||
|         $params = [ | ||||
|             'merchant_order_id' => $order->trade_no, | ||||
|             'price_amount' => $order->total_amount / 100, | ||||
|             'price_currency' => 'CNY', | ||||
|             'title' => '支付单号:' . $order->trade_no, | ||||
|             'description' => '充值:' . $order->total_amount / 100 . ' 元', | ||||
|             'callback_url' => url('/api/v1/guest/order/bitpayXNotify'), | ||||
|             'success_url' => config('v2board.app_url', env('APP_URL')) . '/#/order', | ||||
|             'cancel_url' => config('v2board.app_url', env('APP_URL')) . '/#/order' | ||||
|         ]; | ||||
|         $strToSign = $bitpayX->prepareSignId($params['merchant_order_id']); | ||||
|         $params['token'] = $bitpayX->sign($strToSign); | ||||
|         $result = $bitpayX->mprequest($params); | ||||
|         Log::info('bitpayXSubmit: ' . json_encode($result)); | ||||
|         return isset($result['payment_url']) ? $result['payment_url'] : false; | ||||
|     } | ||||
|  | ||||
|     private function payTaro($order) | ||||
|     { | ||||
|         $payTaro = new PayTaro(config('v2board.paytaro_app_id'), config('v2board.paytaro_app_secret')); | ||||
|         $result = $payTaro->pay([ | ||||
|             'app_id' => config('v2board.paytaro_app_id'), | ||||
|             'out_trade_no' => $order->trade_no, | ||||
|             'total_amount' => $order->total_amount, | ||||
|             'notify_url' => url('/api/v1/guest/order/payTaroNotify'), | ||||
|             'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order' | ||||
|         ]); | ||||
|         return $result; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Http/Controllers/User/PlanController.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								app/Http/Controllers/User/PlanController.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Models\Plan; | ||||
|  | ||||
| class PlanController extends Controller | ||||
| { | ||||
|     public function fetch(Request $request) | ||||
|     { | ||||
|         if ($request->input('id')) { | ||||
|             $plan = Plan::where('id', $request->input('id')) | ||||
|                 ->first(); | ||||
|             if (!$plan) { | ||||
|                 abort(500, '该订阅不存在'); | ||||
|             } | ||||
|             return response([ | ||||
|                 'data' => $plan | ||||
|             ]); | ||||
|         } | ||||
|         $plan = Plan::where('show', 1) | ||||
|             ->get(); | ||||
|         return response([ | ||||
|             'data' => $plan | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										74
									
								
								app/Http/Controllers/User/ServerController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/Http/Controllers/User/ServerController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Cache; | ||||
| use App\Models\Server; | ||||
| use App\Models\ServerLog; | ||||
| use App\Models\User; | ||||
|  | ||||
| use App\Utils\Helper; | ||||
|  | ||||
| class ServerController extends Controller | ||||
| { | ||||
|     public function fetch(Request $request) | ||||
|     { | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         $server = []; | ||||
|         if ($user->expired_at > time()) { | ||||
|             $servers = Server::where('show', 1) | ||||
|                 ->orderBy('name') | ||||
|                 ->get(); | ||||
|             foreach ($servers as $item) { | ||||
|                 $groupId = json_decode($item['group_id']); | ||||
|                 if (in_array($user->group_id, $groupId)) { | ||||
|                     array_push($server, $item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         for ($i = 0; $i < count($server); $i++) { | ||||
|             $server[$i]['link'] = Helper::buildVmessLink($server[$i], $user); | ||||
|             if ($server[$i]['parent_id']) { | ||||
|                 $server[$i]['last_check_at'] = Cache::get('server_last_check_at_' . $server[$i]['parent_id']); | ||||
|             } else { | ||||
|                 $server[$i]['last_check_at'] = Cache::get('server_last_check_at_' . $server[$i]['id']); | ||||
|             } | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => $server | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function logFetch(Request $request) | ||||
|     { | ||||
|         $type = $request->input('type') ? $request->input('type') : 0; | ||||
|         $current = $request->input('current') ? $request->input('current') : 1; | ||||
|         $pageSize = $request->input('pageSize') >= 10 ? $request->input('pageSize') : 10; | ||||
|         $serverLogModel = ServerLog::where('user_id', $request->session()->get('id')) | ||||
|             ->orderBy('created_at', 'DESC'); | ||||
|         switch ($type) { | ||||
|             case 0: | ||||
|                 $serverLogModel->where('created_at', '>=', strtotime(date('Y-m-d'))); | ||||
|                 break; | ||||
|             case 1: | ||||
|                 $serverLogModel->where('created_at', '>=', strtotime(date('Y-m-d')) - 604800); | ||||
|                 break; | ||||
|             case 2: | ||||
|                 $serverLogModel->where('created_at', '>=', strtotime(date('Y-m-1'))); | ||||
|         } | ||||
|         $sum = [ | ||||
|             'u' => $serverLogModel->sum('u'), | ||||
|             'd' => $serverLogModel->sum('d') | ||||
|         ]; | ||||
|         $total = $serverLogModel->count(); | ||||
|         $res = $serverLogModel->forPage($current, $pageSize) | ||||
|             ->get(); | ||||
|         return response([ | ||||
|             'data' => $res, | ||||
|             'total' => $total, | ||||
|             'sum' => $sum | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										144
									
								
								app/Http/Controllers/User/TicketController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								app/Http/Controllers/User/TicketController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use App\Http\Requests\TicketSave; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Models\Ticket; | ||||
| use App\Models\TicketMessage; | ||||
| use App\Utils\Helper; | ||||
| use Illuminate\Support\Facades\DB; | ||||
|  | ||||
| class TicketController extends Controller | ||||
| { | ||||
|     public function fetch(Request $request) | ||||
|     { | ||||
|         if ($request->input('id')) { | ||||
|             $ticket = Ticket::where('id', $request->input('id')) | ||||
|                 ->where('user_id', $request->session()->get('id')) | ||||
|                 ->first(); | ||||
|             if (!$ticket) { | ||||
|                 abort(500, '工单不存在'); | ||||
|             } | ||||
|             $ticket['message'] = TicketMessage::where('ticket_id', $ticket->id)->get(); | ||||
|             for ($i = 0; $i < count($ticket['message']); $i++) { | ||||
|                 if ($ticket['message'][$i]['user_id'] == $ticket->user_id) { | ||||
|                     $ticket['message'][$i]['is_me'] = true; | ||||
|                 } else { | ||||
|                     $ticket['message'][$i]['is_me'] = false; | ||||
|                 } | ||||
|             } | ||||
|             return response([ | ||||
|                 'data' => $ticket | ||||
|             ]); | ||||
|         } | ||||
|         $ticket = Ticket::where('user_id', $request->session()->get('id')) | ||||
|             ->orderBy('created_at', 'DESC') | ||||
|             ->get(); | ||||
|         for ($i = 0; $i < count($ticket); $i++) { | ||||
|             if ($ticket[$i]['last_reply_user_id'] == $request->session()->get('id')) { | ||||
|                 $ticket[$i]['reply_status'] = 0; | ||||
|             } else { | ||||
|                 $ticket[$i]['reply_status'] = 1; | ||||
|             } | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => $ticket | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function save(TicketSave $request) | ||||
|     { | ||||
|         DB::beginTransaction(); | ||||
|         $ticket = Ticket::create(array_merge($request->only([ | ||||
|             'subject', | ||||
|             'level' | ||||
|         ]), [ | ||||
|             'user_id' => $request->session()->get('id'), | ||||
|             'last_reply_user_id' => $request->session()->get('id') | ||||
|         ])); | ||||
|         if (!$ticket) { | ||||
|             DB::rollback(); | ||||
|             abort(500, '工单创建失败'); | ||||
|         } | ||||
|         $ticketMessage = TicketMessage::create([ | ||||
|             'user_id' => $request->session()->get('id'), | ||||
|             'ticket_id' => $ticket->id, | ||||
|             'message' => $request->input('message') | ||||
|         ]); | ||||
|         if (!$ticketMessage) { | ||||
|             DB::rollback(); | ||||
|             abort(500, '工单创建失败'); | ||||
|         } | ||||
|         DB::commit(); | ||||
|         return response([ | ||||
|             'data' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function reply(Request $request) | ||||
|     { | ||||
|         if (empty($request->input('id'))) { | ||||
|             abort(500, '参数错误'); | ||||
|         } | ||||
|         if (empty($request->input('message'))) { | ||||
|             abort(500, '消息不能为空'); | ||||
|         } | ||||
|         $ticket = Ticket::where('id', $request->input('id')) | ||||
|             ->where('user_id', $request->session()->get('id')) | ||||
|             ->first(); | ||||
|         if (!$ticket) { | ||||
|             abort(500, '工单不存在'); | ||||
|         } | ||||
|         if ($ticket->status) { | ||||
|             abort(500, '工单已关闭,无法回复'); | ||||
|         } | ||||
|         if ($request->session()->get('id') == $this->getLastMessage($ticket->id)->user_id) { | ||||
|             abort(500, '请等待技术支持回复'); | ||||
|         } | ||||
|         DB::beginTransaction(); | ||||
|         $ticketMessage = TicketMessage::create([ | ||||
|             'user_id' => $request->session()->get('id'), | ||||
|             'ticket_id' => $ticket->id, | ||||
|             'message' => $request->input('message') | ||||
|         ]); | ||||
|         $ticket->last_reply_user_id = $request->session()->get('id'); | ||||
|         if (!$ticketMessage || !$ticket->save()) { | ||||
|             DB::rollback(); | ||||
|             abort(500, '工单回复失败'); | ||||
|         } | ||||
|         DB::commit(); | ||||
|         return response([ | ||||
|             'data' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public function close(Request $request) | ||||
|     { | ||||
|         if (empty($request->input('id'))) { | ||||
|             abort(500, '参数错误'); | ||||
|         } | ||||
|         $ticket = Ticket::where('id', $request->input('id')) | ||||
|             ->where('user_id', $request->session()->get('id')) | ||||
|             ->first(); | ||||
|         if (!$ticket) { | ||||
|             abort(500, '工单不存在'); | ||||
|         } | ||||
|         $ticket->status = 1; | ||||
|         if (!$ticket->save()) { | ||||
|             abort(500, '关闭失败'); | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     private function getLastMessage($ticketId) | ||||
|     { | ||||
|         return TicketMessage::where('ticket_id', $ticketId) | ||||
|             ->orderBy('id', 'DESC') | ||||
|             ->first(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										76
									
								
								app/Http/Controllers/User/TutorialController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								app/Http/Controllers/User/TutorialController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Models\User; | ||||
| use App\Models\Tutorial; | ||||
|  | ||||
| class TutorialController extends Controller | ||||
| { | ||||
|     public function getSubscribeUrl(Request $request) | ||||
|     { | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         return response([ | ||||
|             'data' => [ | ||||
|                 'subscribe_url' => config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'] | ||||
|             ] | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getAppleID(Request $request) | ||||
|     { | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         if ($user->expired_at < time()) { | ||||
|             return response([ | ||||
|                 'data' => [ | ||||
|                 ] | ||||
|             ]); | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => [ | ||||
|                 'apple_id' => config('v2board.apple_id'), | ||||
|                 'apple_id_password' => config('v2board.apple_id_password') | ||||
|             ] | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function fetch(Request $request) | ||||
|     { | ||||
|         if ($request->input('id')) { | ||||
|             $tutorial = Tutorial::where('show', 1) | ||||
|                 ->where('id', $request->input('id')) | ||||
|                 ->first(); | ||||
|             if (!$tutorial) { | ||||
|                 abort(500, '教程不存在'); | ||||
|             } | ||||
|             return response([ | ||||
|                 'data' => $tutorial | ||||
|             ]); | ||||
|         } | ||||
|         $tutorial = Tutorial::select(['id', 'title', 'description', 'icon']) | ||||
|             ->where('show', 1) | ||||
|             ->get(); | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         $response = [ | ||||
|             'data' => [ | ||||
|                 'tutorials' => $tutorial, | ||||
|                 'safe_area_var' => [ | ||||
|                     'subscribe_url' => config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'], | ||||
|                     'app_name' => config('v2board.app_name', 'V2board'), | ||||
|                     'apple_id' => $user->expired_at > time() ? config('v2board.apple_id', '管理员暂无提供AppleID信息') : '账号过期或未订阅', | ||||
|                     'apple_id_password' => $user->expired_at > time() ? config('v2board.apple_id_password', '管理员暂无提供AppleID信息') : '账号过期或未订阅' | ||||
|                 ] | ||||
|             ] | ||||
|         ]; | ||||
|         // fuck support shadowrocket urlsafeb64 subscribe | ||||
|         $response['data']['safe_area_var']['b64_subscribe_url'] = str_replace( | ||||
|             array('+', '/', '='), | ||||
|             array('-', '_', ''), | ||||
|             base64_encode($response['data']['safe_area_var']['subscribe_url']) | ||||
|         ); | ||||
|         // end | ||||
|         return response($response); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										135
									
								
								app/Http/Controllers/User/UserController.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										135
									
								
								app/Http/Controllers/User/UserController.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,135 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers\User; | ||||
|  | ||||
| use App\Http\Controllers\Controller; | ||||
| use App\Http\Requests\UserUpdate; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Models\User; | ||||
| use App\Models\Plan; | ||||
| use App\Models\Server; | ||||
| use App\Models\Ticket; | ||||
| use App\Utils\Helper; | ||||
| use App\Models\Order; | ||||
| use App\Models\ServerLog; | ||||
|  | ||||
| class UserController extends Controller | ||||
| { | ||||
|     public function logout(Request $request) | ||||
|     { | ||||
|         return response([ | ||||
|             'data' => $request->session()->flush() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function changePassword(Request $request) | ||||
|     { | ||||
|         if (empty($request->input('old_password'))) { | ||||
|             abort(500, '旧密码不能为空'); | ||||
|         } | ||||
|         if (empty($request->input('new_password'))) { | ||||
|             abort(500, '新密码不能为空'); | ||||
|         } | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         if (!password_verify($request->input('old_password'), $user->password)) { | ||||
|             abort(500, '旧密码有误'); | ||||
|         } | ||||
|         $user->password = password_hash($request->input('new_password'), PASSWORD_DEFAULT); | ||||
|         if (!$user->save()) { | ||||
|             abort(500, '保存失败'); | ||||
|         } | ||||
|         $request->session()->flush(); | ||||
|         return response([ | ||||
|             'data' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function info(Request $request) | ||||
|     { | ||||
|         $user = User::where('id', $request->session()->get('id')) | ||||
|             ->select([ | ||||
|                 'email', | ||||
|                 'transfer_enable', | ||||
|                 'last_login_at', | ||||
|                 'created_at', | ||||
|                 'enable', | ||||
|                 'is_admin', | ||||
|                 'remind_expire', | ||||
|                 'remind_traffic', | ||||
|                 'expired_at', | ||||
|                 'balance', | ||||
|                 'commission_balance', | ||||
|                 'plan_id' | ||||
|             ]) | ||||
|             ->first(); | ||||
|         $user['avatar_url'] = 'https://cdn.v2ex.com/gravatar/' . md5($user->email) . '?s=64&d=identicon'; | ||||
|         return response([ | ||||
|             'data' => $user | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getStat(Request $request) | ||||
|     { | ||||
|         $stat = [ | ||||
|             Order::where('status', 0) | ||||
|                 ->where('user_id', $request->session()->get('id')) | ||||
|                 ->count(), | ||||
|             Ticket::where('status', 0) | ||||
|                 ->where('user_id', $request->session()->get('id')) | ||||
|                 ->count(), | ||||
|             User::where('invite_user_id', $request->session()->get('id')) | ||||
|                 ->count() | ||||
|         ]; | ||||
|         return response([ | ||||
|             'data' => $stat | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getSubscribe(Request $request) | ||||
|     { | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         if ($user->plan_id) { | ||||
|             $user['plan'] = Plan::find($user->plan_id); | ||||
|             if (!$user['plan']) { | ||||
|                 abort(500, '订阅计划不存在'); | ||||
|             } | ||||
|         } | ||||
|         $user['subscribe_url'] = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token']; | ||||
|         return response([ | ||||
|             'data' => $user | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function resetSecurity(Request $request) | ||||
|     { | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         $user->v2ray_uuid = Helper::guid(true); | ||||
|         $user->token = Helper::guid(); | ||||
|         if (!$user->save()) { | ||||
|             abort(500, '重置失败'); | ||||
|         } | ||||
|         return response([ | ||||
|             'data' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function update(UserUpdate $request) | ||||
|     { | ||||
|         $updateData = $request->only([ | ||||
|             'remind_expire', | ||||
|             'remind_traffic' | ||||
|         ]); | ||||
|  | ||||
|         $user = User::find($request->session()->get('id')); | ||||
|         if (!$user) { | ||||
|             abort(500, '该用户不存在'); | ||||
|         } | ||||
|         if (!$user->update($updateData)) { | ||||
|             abort(500, '保存失败'); | ||||
|         } | ||||
|  | ||||
|         return response([ | ||||
|             'data' => true | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user