作者 李宇航

合并分支 'master-server' 到 'master'

Master server



查看合并请求 !992
@@ -35,7 +35,7 @@ class PayStripeApi @@ -35,7 +35,7 @@ class PayStripeApi
35 ]; 35 ];
36 36
37 // 构造函数设置密钥 37 // 构造函数设置密钥
38 - public function __construct($secretKey) 38 + public function __construct()
39 { 39 {
40 $this->secretKey = 'sk_test_51MyseXIWCYVeLww1tbPZzRe1Qk4lS5d2VLiDjpju7G0ToiX1RJcFinQXNlftq9eCjZE0n2gjaz1mfy1g0mxTusdf00m636Gv62'; 40 $this->secretKey = 'sk_test_51MyseXIWCYVeLww1tbPZzRe1Qk4lS5d2VLiDjpju7G0ToiX1RJcFinQXNlftq9eCjZE0n2gjaz1mfy1g0mxTusdf00m636Gv62';
41 } 41 }
@@ -79,13 +79,13 @@ class PayStripeApi @@ -79,13 +79,13 @@ class PayStripeApi
79 * @method :post 79 * @method :post
80 * @time :2024/12/24 10:38 80 * @time :2024/12/24 10:38
81 */ 81 */
82 - public function createPaymentIntent($amount, $currency = 'usd') 82 + public function createPaymentIntent($amount, $currency = 'usd', $paymentMethodTypes = 'card')
83 { 83 {
84 $url = "https://api.stripe.com/v1/payment_intents"; 84 $url = "https://api.stripe.com/v1/payment_intents";
85 $data = [ 85 $data = [
86 'amount' => $amount, 86 'amount' => $amount,
87 'currency' => $currency, 87 'currency' => $currency,
88 - 'payment_method_types[]' => $this->currency_types[$currency], 88 + 'payment_method_types[]' => $paymentMethodTypes,
89 ]; 89 ];
90 return $this->sendRequest($url, 'POST', $data); 90 return $this->sendRequest($url, 'POST', $data);
91 } 91 }
@@ -104,87 +104,6 @@ class PayStripeApi @@ -104,87 +104,6 @@ class PayStripeApi
104 } 104 }
105 105
106 /** 106 /**
107 - * @remark :创建客户  
108 - * @name :createCustomer  
109 - * @author :lyh  
110 - * @method :post  
111 - * @time :2024/12/24 10:41  
112 - */  
113 - public function createCustomer($name, $email, $description = '')  
114 - {  
115 - $url = "https://api.stripe.com/v1/customers";  
116 - $data = [  
117 - 'name' => $name,  
118 - 'email' => $email,  
119 - 'description' => $description  
120 - ];  
121 - return $this->sendRequest($url, 'POST', $data);  
122 - }  
123 -  
124 - /**  
125 - * @remark :查询客户  
126 - * @name :retrieveCustomer  
127 - * @author :lyh  
128 - * @method :post  
129 - * @time :2024/12/24 10:41  
130 - */  
131 - public function retrieveCustomer($customerId)  
132 - {  
133 - $url = "https://api.stripe.com/v1/customers/{$customerId}";  
134 - return $this->sendRequest($url, 'GET');  
135 - }  
136 -  
137 - /**  
138 - * @remark :删除客户  
139 - * @name :deleteCustomer  
140 - * @author :lyh  
141 - * @method :post  
142 - * @time :2024/12/24 10:42  
143 - */  
144 - public function deleteCustomer($customerId)  
145 - {  
146 - $url = "https://api.stripe.com/v1/customers/{$customerId}";  
147 - return $this->sendRequest($url, 'DELETE');  
148 - }  
149 -  
150 - /**  
151 - * @remark :创建支付方法  
152 - * @name :createPaymentMethod  
153 - * @author :lyh  
154 - * @method :post  
155 - * @time :2024/12/24 10:42  
156 - */  
157 - public function createPaymentMethod($cardNumber, $expMonth, $expYear, $cvc)  
158 - {  
159 - $url = "https://api.stripe.com/v1/payment_methods";  
160 - $data = [  
161 - 'type' => 'card',  
162 - 'card[number]' => $cardNumber,  
163 - 'card[exp_month]' => $expMonth,  
164 - 'card[exp_year]' => $expYear,  
165 - 'card[cvc]' => $cvc,  
166 - ];  
167 -  
168 - return $this->sendRequest($url, 'POST', $data);  
169 - }  
170 -  
171 - /**  
172 - * @remark :绑定支付方法到客户  
173 - * @name :attachPaymentMethodToCustomer  
174 - * @author :lyh  
175 - * @method :post  
176 - * @time :2024/12/24 10:42  
177 - */  
178 - public function attachPaymentMethodToCustomer($paymentMethodId, $customerId)  
179 - {  
180 - $url = "https://api.stripe.com/v1/payment_methods/{$paymentMethodId}/attach";  
181 - $data = [  
182 - 'customer' => $customerId,  
183 - ];  
184 - return $this->sendRequest($url, 'POST', $data);  
185 - }  
186 -  
187 - /**  
188 * @remark :创建退款 107 * @remark :创建退款
189 * @name :createRefund 108 * @name :createRefund
190 * @author :lyh 109 * @author :lyh
@@ -198,7 +117,6 @@ class PayStripeApi @@ -198,7 +117,6 @@ class PayStripeApi
198 if ($amount) { 117 if ($amount) {
199 $data['amount'] = $amount; 118 $data['amount'] = $amount;
200 } 119 }
201 -  
202 return $this->sendRequest($url, 'POST', $data); 120 return $this->sendRequest($url, 'POST', $data);
203 } 121 }
204 122
@@ -216,50 +134,89 @@ class PayStripeApi @@ -216,50 +134,89 @@ class PayStripeApi
216 } 134 }
217 135
218 /** 136 /**
219 - * @remark :创建订阅  
220 - * @name :createSubscription  
221 - * @author :lyh  
222 - * @method :post  
223 - * @time :2024/12/24 10:42  
224 - */  
225 - public function createSubscription($customerId, $priceId)  
226 - {  
227 - $url = "https://api.stripe.com/v1/subscriptions";  
228 - $data = [  
229 - 'customer' => $customerId,  
230 - 'items[0][price]' => $priceId,  
231 - ];  
232 - return $this->sendRequest($url, 'POST', $data);  
233 - }  
234 -  
235 - /**  
236 - * @remark :取消订阅  
237 - * @name :cancelSubscription 137 + * @remark :处理 Webhook
  138 + * @name :handleWebhook
238 * @author :lyh 139 * @author :lyh
239 * @method :post 140 * @method :post
240 * @time :2024/12/24 10:43 141 * @time :2024/12/24 10:43
241 */ 142 */
242 - public function cancelSubscription($subscriptionId) 143 + public static function handleWebhook()
243 { 144 {
244 - $url = "https://api.stripe.com/v1/subscriptions/{$subscriptionId}";  
245 - return $this->sendRequest($url, 'DELETE'); 145 + try {
  146 + // Webhook 签名密钥(从 Stripe 仪表盘获取)
  147 + $endpointSecret = 'whsec_garhW2TrCIrduyM3rve9mFS2sn69B9Yt';
  148 + // 获取原始请求内容
  149 + $payload = request()->getContent();
  150 + // 获取 Stripe 签名头
  151 + $sigHeader = request()->header('Stripe-Signature');
  152 + // 验证签名
  153 + if (!self::verifySignature($payload, $sigHeader, $endpointSecret)) {
  154 + return [
  155 + 'code' => '201',
  156 + 'message' => 'Invalid signature',
  157 + 'details' => [
  158 + 'payload' => $payload,
  159 + 'sigHeader' => $sigHeader,
  160 + 'endpointSecret' => $endpointSecret,
  161 + ],
  162 + ]; // 返回 400 Bad Request 状态码;
  163 + }
  164 + $event = json_decode($payload, true);
  165 + // 获取事件类型
  166 + $eventType = $event['type'];
  167 + $eventData = $event['data']['object'];
  168 + // 根据事件类型处理
  169 + switch ($eventType) {
  170 + case 'payment_intent.succeeded':
  171 + // 处理支付成功逻辑
  172 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export('success', true) . PHP_EOL, FILE_APPEND);
  173 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export($eventType, true) . PHP_EOL, FILE_APPEND);
  174 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export($eventData, true) . PHP_EOL, FILE_APPEND);
  175 + $paymentIntentId = $eventData['id'];
  176 + break;
  177 + case 'payment_intent.payment_failed':
  178 + // 处理支付失败逻辑
  179 + $error = $eventData['last_payment_error'];
  180 + break;
  181 + case 'charge.refunded':
  182 + // 处理退款逻辑
  183 + $chargeId = $eventData['id'];
  184 + break;
  185 + default:
  186 + throw new \Exception('Unhandled event type: ' . $eventType);
  187 + }
  188 + return $event;
  189 + } catch (Exception $e) {
  190 + throw new \Exception('Webhook Error: ' . $e->getMessage());
  191 + }
246 } 192 }
247 193
248 /** 194 /**
249 - * @remark :处理 Webhook  
250 - * @name :handleWebhook 195 + * @remark :验证签名
  196 + * @name :verifySignature
251 * @author :lyh 197 * @author :lyh
252 * @method :post 198 * @method :post
253 - * @time :2024/12/24 10:43 199 + * @time :2024/12/24 15:55
254 */ 200 */
255 - public static function handleWebhook($payload, $sigHeader, $endpointSecret) 201 + public static function verifySignature($payload, $sigHeader, $endpointSecret)
256 { 202 {
257 - try {  
258 - $event = json_decode($payload, true);  
259 - // 检查事件类型  
260 - return $event; // 返回解析后的事件  
261 - } catch (Exception $e) {  
262 - throw new Exception('Webhook Error: ' . $e->getMessage()); 203 + // 解析 Signature Header,获取 timestamp 和签名
  204 + if (!preg_match('/t=(\d+),v1=([a-f0-9]+)/', $sigHeader, $matches)) {
  205 + return false; // 签名格式错误
  206 + }
  207 + $timestamp = $matches[1]; // 提取时间戳
  208 + $receivedSignature = $matches[2]; // 提取签名
  209 + // 防止重放攻击:检查时间戳是否在 5 分钟以内
  210 + $currentTimestamp = time();
  211 + if (abs($currentTimestamp - $timestamp) > 300) {
  212 + return false; // 签名过期
263 } 213 }
  214 + // 计算预期签名
  215 + $signedPayload = "{$timestamp}.{$payload}";
  216 + $expectedSignature = hash_hmac('sha256', $signedPayload, $endpointSecret);
  217 + // 比较签名是否匹配
  218 + return hash_equals($expectedSignature, $receivedSignature);
264 } 219 }
  220 +
  221 +
265 } 222 }
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :PayStripeController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2024/12/24 16:42
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Api;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Helper\PayStripeApi;
  14 +
  15 +class PayStripeController extends BaseController
  16 +{
  17 + /**
  18 + * @remark :回调方法
  19 + * @name :handleWebhook
  20 + * @author :lyh
  21 + * @method :post
  22 + * @time :2024/12/24 15:41
  23 + */
  24 + public function handleWebhook(){
  25 + $pay = new PayStripeApi();
  26 + $data = $pay->handleWebhook();
  27 + $this->response('success',Code::SUCCESS,$data);
  28 + }
  29 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :Extension3059ModuleController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2024/12/25 9:44
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Bside\ExtensionModule;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Helper\PayStripeApi;
  14 +use App\Http\Controllers\Bside\BaseController;
  15 +use App\Models\ExtentModule\ExtensionModuleValue;
  16 +
  17 +class Extension3059ModuleController extends BaseController
  18 +{
  19 + /**
  20 + * @remark :获取当前所有的商品列表
  21 + * @name :getProductLists
  22 + * @author :lyh
  23 + * @method :post
  24 + * @time :2024/12/25 9:37
  25 + */
  26 + public function getProductLists(){
  27 + $this->param['module_id'] = $this->param['module_id'] ?? 2;//默认加载商品数据
  28 + $searchParam = [
  29 + 'module_id'=>$this->param['module_id'],
  30 + ];
  31 + $data = [];
  32 + $moduleValueModel = new ExtensionModuleValue();
  33 + $lists = $moduleValueModel->list($searchParam);
  34 + if(!empty($lists)){
  35 + foreach ($lists as $k => $v){
  36 + $data[$v['uuid']][$v['field_id']] = $v['value'];
  37 + $data[$v['uuid']]['created_at'] = $v['created_at'];
  38 + }
  39 + }
  40 + $resultData = [];
  41 + foreach ($data as $k => $v){
  42 + $v['uuid'] = $k;
  43 + $resultData[] = $v;
  44 + }
  45 + $this->response('success',Code::SUCCESS,$resultData);
  46 + }
  47 +
  48 +
  49 +
  50 + /**
  51 + * @remark :编辑订单详情
  52 + * @name :editOrderDetail
  53 + * @author :lyh
  54 + * @method :post
  55 + * @time :2024/12/25 10:26
  56 + */
  57 + public function saveOrderDetail(){
  58 + $this->request->validate([
  59 + 'data'=>'required',
  60 + 'amount'=>'required',
  61 + 'currency'=>'required',
  62 + 'payment_method_types'=>'required',
  63 + ],[
  64 + 'data.required' => '数据不能为空',
  65 + 'amount.required' => '金额不能为空',
  66 + 'currency.required' => '币种不能为空',
  67 + 'payment_method_types.required' => '支付方式不能为空',
  68 + ]);
  69 + $this->param['module_id'] = 1;//默认订单模块
  70 + $moduleValueModel = new ExtensionModuleValue();
  71 + $info = $moduleValueModel->where('module_id',$this->param['module_id'])->orderBy('uuid','desc')->first();
  72 + if(empty($info)){
  73 + $uuid = 1;
  74 + }else{
  75 + $info = $info->toArray();
  76 + $uuid = $info['uuid'] + 1;
  77 + }
  78 + $saveData = [];
  79 + try {
  80 + //生成订单id
  81 + $saveData[] =['uuid'=>$uuid,'module_id'=>$this->param['module_id'],'field_id'=>1,'value'=>md5(uniqid(mt_rand(), true))];
  82 + $data = $this->param['data'];
  83 + $moduleValueModel = new ExtensionModuleValue();
  84 + foreach ($data as $k => $v){
  85 + $saveData[] = [
  86 + 'uuid'=>$uuid,
  87 + 'module_id'=>$this->param['module_id'],
  88 + 'field_id'=>$v['field_id'],
  89 + 'value'=>$v['value']
  90 + ];
  91 + }
  92 + $pay = new PayStripeApi();
  93 + $data = $pay->createPaymentIntent($this->param['amount'],$this->param['currency'],$this->param['payment_method_types']);
  94 + $saveData[] = ['uuid'=>$uuid,'module_id'=>$this->param['module_id'],'field_id'=>8,'value'=>$data['id'] ?? '未获取到支付意愿,请重新获取'];
  95 + $moduleValueModel->insertAll($saveData);
  96 + }catch (\Exception $e){
  97 + $this->fail('error,请联系管理员');
  98 + }
  99 + $this->response('success',Code::SUCCESS,['uuid'=>$uuid,'data'=>$data]);
  100 + }
  101 +}
@@ -185,13 +185,7 @@ class ExtensionModuleController extends BaseController @@ -185,13 +185,7 @@ class ExtensionModuleController extends BaseController
185 foreach ($data as $k => $v){ 185 foreach ($data as $k => $v){
186 $info = $moduleValueModel->read(['uuid'=>$this->param['uuid'],'field_id'=>$v['field_id'],'module_id'=>$this->param['module_id']]); 186 $info = $moduleValueModel->read(['uuid'=>$this->param['uuid'],'field_id'=>$v['field_id'],'module_id'=>$this->param['module_id']]);
187 if($info === false){ 187 if($info === false){
188 - if($this->user['project_id'] == 2205 && $this->param['module_id'] == 1){  
189 - if($v['field_id'] == 12 && !empty($v['value'])){//下拉框数据  
190 - if($v['value'] != 'Ordered'){  
191 - $this->fail('请从第一个流程开始选择。');  
192 - }  
193 - }  
194 - } 188 + $this->edit2205ModuleValue($v);
195 $data = [ 189 $data = [
196 'uuid'=>$this->param['uuid'], 190 'uuid'=>$this->param['uuid'],
197 'module_id'=>$this->param['module_id'], 191 'module_id'=>$this->param['module_id'],
@@ -200,33 +194,53 @@ class ExtensionModuleController extends BaseController @@ -200,33 +194,53 @@ class ExtensionModuleController extends BaseController
200 ]; 194 ];
201 $moduleValueModel->addReturnId($data); 195 $moduleValueModel->addReturnId($data);
202 }else{ 196 }else{
203 - if($this->user['project_id'] == 2205 && $this->param['module_id'] == 1){  
204 - if($v['field_id'] == 12 && (!empty($v['value']) && !empty($info['value']))){//下拉框数据  
205 - $filedModel = new ExtensionModuleField();  
206 - $fileInfo = $filedModel->read(['id'=>12]);//获取当前下拉框的数据  
207 - $statusData = json_decode($fileInfo['data'],true);  
208 - $status_data = [];  
209 - $number = 1;  
210 - foreach ($statusData as $value){  
211 - $status_data[$value] = $number;  
212 - $number++;  
213 - }  
214 - if(($status_data[$info['value']]) != $status_data[$v['value']]){  
215 - if(($status_data[$info['value']] + 1) != $status_data[$v['value']]){  
216 - $this->fail('流程控制不能跳流程选择');  
217 - }  
218 - }  
219 - if($status_data[$info['value']] > $status_data[$v['value']]){  
220 - $this->fail('流程控制不能回滚');  
221 - }  
222 - }  
223 - } 197 + $this->edit2205ModuleValue($v);
224 $moduleValueModel->edit(['value'=>$v['value'] ?? ''],['id'=>$info['id']]); 198 $moduleValueModel->edit(['value'=>$v['value'] ?? ''],['id'=>$info['id']]);
225 } 199 }
226 } 200 }
227 $this->response('success',Code::SUCCESS,['uuid'=>$this->param['uuid']]); 201 $this->response('success',Code::SUCCESS,['uuid'=>$this->param['uuid']]);
228 } 202 }
229 203
  204 + /**
  205 + * @remark :2205项目单独处理
  206 + * @name :edit2205ModuleValue
  207 + * @author :lyh
  208 + * @method :post
  209 + * @time :2024/12/25 10:12
  210 + */
  211 + public function edit2205ModuleValue($v){
  212 + if(isset($this->param['id']) && !empty($this->param['id'])){
  213 + if($this->user['project_id'] == 2205 && $this->param['module_id'] == 1){
  214 + if($v['field_id'] == 12 && (!empty($v['value']) && !empty($info['value']))){//下拉框数据
  215 + $filedModel = new ExtensionModuleField();
  216 + $fileInfo = $filedModel->read(['id'=>12]);//获取当前下拉框的数据
  217 + $statusData = json_decode($fileInfo['data'],true);
  218 + $status_data = [];
  219 + $number = 1;
  220 + foreach ($statusData as $value){
  221 + $status_data[$value] = $number;
  222 + $number++;
  223 + }
  224 + if(($status_data[$info['value']]) != $status_data[$v['value']]){
  225 + if(($status_data[$info['value']] + 1) != $status_data[$v['value']]){
  226 + $this->fail('流程控制不能跳流程选择');
  227 + }
  228 + }
  229 + if($status_data[$info['value']] > $status_data[$v['value']]){
  230 + $this->fail('流程控制不能回滚');
  231 + }
  232 + }
  233 + }
  234 + }else{
  235 + if($this->user['project_id'] == 2205 && $this->param['module_id'] == 1){
  236 + if($v['field_id'] == 12 && !empty($v['value'])){//下拉框数据
  237 + if($v['value'] != 'Ordered'){
  238 + $this->fail('请从第一个流程开始选择。');
  239 + }
  240 + }
  241 + }
  242 + }
  243 + }
230 244
231 /** 245 /**
232 * @remark :新增數據 246 * @remark :新增數據
@@ -252,13 +266,7 @@ class ExtensionModuleController extends BaseController @@ -252,13 +266,7 @@ class ExtensionModuleController extends BaseController
252 $data = $this->param['data']; 266 $data = $this->param['data'];
253 $moduleValueModel = new ExtensionModuleValue(); 267 $moduleValueModel = new ExtensionModuleValue();
254 foreach ($data as $k => $v){ 268 foreach ($data as $k => $v){
255 - if($this->user['project_id'] == 2205 && $this->param['module_id'] == 1){  
256 - if($v['field_id'] == 12 && !empty($v['value'])){//下拉框数据  
257 - if($v['value'] != 'Ordered'){  
258 - $this->fail('请重第一个流程开始选择');  
259 - }  
260 - }  
261 - } 269 + $this->edit2205ModuleValue($v);
262 $data = [ 270 $data = [
263 'uuid'=>$uuid, 271 'uuid'=>$uuid,
264 'module_id'=>$this->param['module_id'], 272 'module_id'=>$this->param['module_id'],
@@ -36,7 +36,7 @@ class TestController extends BaseController @@ -36,7 +36,7 @@ class TestController extends BaseController
36 */ 36 */
37 public function ceshi(){ 37 public function ceshi(){
38 $pay = new PayStripeApi(); 38 $pay = new PayStripeApi();
39 - $data = $pay->createPaymentIntent(5000,'cny'); 39 + $data = $pay->createPaymentIntent(5000,'cny','alipay');
40 $this->response('success',Code::SUCCESS,$data); 40 $this->response('success',Code::SUCCESS,$data);
41 } 41 }
42 42
@@ -32,9 +32,9 @@ class ExtensionModuleFieldLogic extends BaseLogic @@ -32,9 +32,9 @@ class ExtensionModuleFieldLogic extends BaseLogic
32 public function saveModuleField(){ 32 public function saveModuleField(){
33 //先查看当前字段是否存在 33 //先查看当前字段是否存在
34 if(isset($this->param['id']) && !empty($this->param['id'])){ 34 if(isset($this->param['id']) && !empty($this->param['id'])){
35 - $info = $this->model->read(['field_name'=>$this->param['field_name'],'id'=>['!=',$this->param['id']]]); 35 + $info = $this->model->read(['field_name'=>$this->param['field_name'],'module_id'=>$this->param['module_id'],'id'=>['!=',$this->param['id']]]);
36 }else{ 36 }else{
37 - $info = $this->model->read(['field_name'=>$this->param['field_name']]); 37 + $info = $this->model->read(['field_name'=>$this->param['field_name'],'module_id'=>$this->param['module_id']]);
38 } 38 }
39 if($info !== false){ 39 if($info !== false){
40 $this->fail('当前字段名已存在'); 40 $this->fail('当前字段名已存在');
@@ -116,6 +116,24 @@ class Base extends Model @@ -116,6 +116,24 @@ class Base extends Model
116 } 116 }
117 117
118 /** 118 /**
  119 + * @remark :批量添加数据
  120 + * @name :addAllReturnId
  121 + * @author :lyh
  122 + * @method :post
  123 + * @time :2024/12/25 11:16
  124 + */
  125 + public function insertAll($data){
  126 + if(is_array($data)){
  127 + foreach ($data as $k => $sonData){
  128 + $sonData['created_at'] = date('Y-m-d H:i:s');
  129 + $sonData['updated_at'] = $sonData['created_at'];
  130 + $data[$k] = $sonData;
  131 + }
  132 + }
  133 + return $this->insert($data);
  134 + }
  135 +
  136 + /**
119 * @remark :统计数量 137 * @remark :统计数量
120 * @name :count 138 * @name :count
121 * @author :lyh 139 * @author :lyh
@@ -17,7 +17,7 @@ use Illuminate\Support\Facades\Route; @@ -17,7 +17,7 @@ use Illuminate\Support\Facades\Route;
17 Route::middleware('auth:sanctum')->get('/user', function (Request $request) { 17 Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
18 return $request->user(); 18 return $request->user();
19 }); 19 });
20 - 20 +Route::any('stripeWebhook', [\App\Http\Controllers\Api\PayStripeController::class, 'handleWebhook'])->name('api.handleWebhook');
21 Route::any('traffic_visit', [\App\Http\Controllers\Api\NoticeController::class, 'trafficVisit'])->name('api.traffic_visit'); 21 Route::any('traffic_visit', [\App\Http\Controllers\Api\NoticeController::class, 'trafficVisit'])->name('api.traffic_visit');
22 Route::get('optimize_project_list', [\App\Http\Controllers\Api\PrivateController::class, 'optimizeProjectList'])->name('api.optimize_project_list'); 22 Route::get('optimize_project_list', [\App\Http\Controllers\Api\PrivateController::class, 'optimizeProjectList'])->name('api.optimize_project_list');
23 Route::get('get_project_route', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectRoute'])->name('api.get_project_route'); 23 Route::get('get_project_route', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectRoute'])->name('api.get_project_route');