bianjunhui пре 1 недеља
родитељ
комит
7a44cccc01

+ 7 - 7
packages/Longyi/RewardPoints/src/Database/Migrations/2026_01_01_000001_create_points_tables.php

@@ -38,7 +38,7 @@ return new class extends Migration
                 $table->boolean('subscribed_balance_update')->default(true);
                 $table->boolean('subscribed_balance_update')->default(true);
                 $table->boolean('subscribed_point_expiration')->default(true);
                 $table->boolean('subscribed_point_expiration')->default(true);
                 $table->timestamp('last_checkout')->useCurrent();
                 $table->timestamp('last_checkout')->useCurrent();
-                
+
                 $table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
                 $table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
             });
             });
         }
         }
@@ -51,9 +51,9 @@ return new class extends Migration
                 $table->unsignedInteger('count_date');
                 $table->unsignedInteger('count_date');
                 $table->unsignedInteger('point');
                 $table->unsignedInteger('point');
                 $table->string('code', 255)->default('');
                 $table->string('code', 255)->default('');
-                $table->dateTime('created')->nullable();
-                $table->dateTime('updated')->nullable();
-                
+                $table->dateTime('created_at')->nullable();
+                $table->dateTime('updated_at')->nullable();
+
                 $table->index('customer_id', 'customer_id_index');
                 $table->index('customer_id', 'customer_id_index');
             });
             });
         }
         }
@@ -73,13 +73,13 @@ return new class extends Migration
                 $table->integer('point_remaining')->default(0);
                 $table->integer('point_remaining')->default(0);
                 $table->boolean('check_time')->default(true);
                 $table->boolean('check_time')->default(true);
                 $table->tinyInteger('status')->default(0);
                 $table->tinyInteger('status')->default(0);
-                
+
                 $table->index('customer_id', 'customer_id_index');
                 $table->index('customer_id', 'customer_id_index');
                 $table->index('transaction_time', 'transaction_time_index');
                 $table->index('transaction_time', 'transaction_time_index');
                 $table->index(['customer_id', 'status'], 'customer_status_index');
                 $table->index(['customer_id', 'status'], 'customer_status_index');
                 $table->index(['customer_id', 'history_order_id'], 'customer_order_index');
                 $table->index(['customer_id', 'history_order_id'], 'customer_order_index');
                 $table->index('expired_time', 'expired_time_index');
                 $table->index('expired_time', 'expired_time_index');
-                
+
                 $table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
                 $table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
             });
             });
         }
         }
@@ -96,7 +96,7 @@ return new class extends Migration
                 $table->string('description')->nullable()->comment('描述');
                 $table->string('description')->nullable()->comment('描述');
                 $table->boolean('is_enabled')->default(true)->comment('是否启用');
                 $table->boolean('is_enabled')->default(true)->comment('是否启用');
                 $table->timestamps();
                 $table->timestamps();
-                
+
                 $table->index('group', 'idx_group');
                 $table->index('group', 'idx_group');
                 $table->index('is_enabled', 'idx_enabled');
                 $table->index('is_enabled', 'idx_enabled');
             });
             });

+ 2 - 3
packages/Longyi/RewardPoints/src/Http/Controllers/RewardPointsController.php

@@ -37,6 +37,7 @@ class RewardPointsController extends Controller
 
 
     public function signIn()
     public function signIn()
     {
     {
+
         $customer = auth()->guard('customer')->user();
         $customer = auth()->guard('customer')->user();
 
 
         if (!$customer) {
         if (!$customer) {
@@ -84,9 +85,7 @@ class RewardPointsController extends Controller
             'sign_date' => $today,
             'sign_date' => $today,
             'count_date' => $countDate,
             'count_date' => $countDate,
             'point' => $points,
             'point' => $points,
-            'code' => uniqid('SIGN_'),
-            'created' => Carbon::now(),
-            'updated' => Carbon::now()
+            'code' => uniqid('SIGN_')
         ]);
         ]);
 
 
         $this->rewardPointRepository->addPoints(
         $this->rewardPointRepository->addPoints(

+ 95 - 0
packages/Longyi/RewardPoints/src/Http/Middleware/ApiCustomerAuthenticate.php

@@ -0,0 +1,95 @@
+<?php
+
+namespace Longyi\RewardPoints\Http\Middleware;
+
+use Closure;
+use Illuminate\Http\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Laravel\Sanctum\PersonalAccessToken;
+
+class ApiCustomerAuthenticate
+{
+    /**
+     * Handle an incoming request.
+     *
+     * 支持三种认证方式:
+     * 1. Session Cookie(传统 Web 登录)
+     * 2. Sanctum Bearer Token(BagistoApi 登录)
+     * 3. Storefront Key + Customer Session
+     *
+     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
+     */
+    public function handle(Request $request, Closure $next): Response
+    {
+        // 方式 1: Session Cookie 认证(传统 Web 登录)
+        if (auth()->guard('customer')->check()) {
+            return $next($request);
+        }
+
+        // 方式 2: Sanctum Bearer Token 认证(BagistoApi 登录)
+        if ($request->bearerToken()) {
+            $customer = $this->authenticateViaSanctum($request);
+
+            if ($customer) {
+                // 将 Sanctum 认证的用户设置到 customer guard
+                auth()->guard('customer')->setUser($customer);
+                return $next($request);
+            }
+        }
+
+        // 都未认证,返回 JSON 错误
+        return response()->json([
+            'error' => 'Please login first',
+            'message' => 'Authentication required. Please login via /customer/login (Session) or /api/shop/customer/login (Token)'
+        ], 401);
+    }
+
+    /**
+     * 通过 Sanctum Token 验证客户
+     *
+     * @return \Webkul\Customer\Models\Customer|null
+     */
+    protected function authenticateViaSanctum(Request $request)
+    {
+        $token = $request->bearerToken();
+
+        if (!$token) {
+            return null;
+        }
+
+        try {
+            // 使用 Sanctum 的 PersonalAccessToken 模型验证
+            $accessToken = PersonalAccessToken::findToken($token);
+
+            if (!$accessToken) {
+                return null;
+            }
+
+            // 检查 Token 是否过期
+            if ($accessToken->expires_at && $accessToken->expires_at->isPast()) {
+                return null;
+            }
+
+            // 获取关联的用户模型
+            $tokenable = $accessToken->tokenable;
+
+            // 确保是 Customer 模型
+            if (!$tokenable || !($tokenable instanceof \Webkul\Customer\Models\Customer)) {
+                return null;
+            }
+
+            // 更新 Token 最后使用时间
+            $accessToken->touch();
+
+            return $tokenable;
+
+        } catch (\Exception $e) {
+            // 记录错误日志(可选)
+            \Log::debug('Sanctum authentication failed', [
+                'error' => $e->getMessage()
+            ]);
+
+            return null;
+        }
+    }
+}

+ 1 - 3
packages/Longyi/RewardPoints/src/Models/RewardPointCustomerSign.php

@@ -14,9 +14,7 @@ class RewardPointCustomerSign extends Model
         'sign_date',
         'sign_date',
         'count_date',
         'count_date',
         'point',
         'point',
-        'code',
-        'created',
-        'updated'
+        'code'
     ];
     ];
 
 
     protected $casts = [
     protected $casts = [

+ 20 - 0
packages/Longyi/RewardPoints/src/Routes/routes.php

@@ -2,6 +2,7 @@
 
 
 use Illuminate\Support\Facades\Route;
 use Illuminate\Support\Facades\Route;
 use Longyi\RewardPoints\Http\Controllers\Admin\GrowthValueController;
 use Longyi\RewardPoints\Http\Controllers\Admin\GrowthValueController;
+use Longyi\RewardPoints\Http\Middleware\ApiCustomerAuthenticate;
 
 
 // 前台路由 - 客户中心
 // 前台路由 - 客户中心
 Route::group(['middleware' => ['web', 'customer'], 'prefix' => 'customer'], function () {
 Route::group(['middleware' => ['web', 'customer'], 'prefix' => 'customer'], function () {
@@ -37,6 +38,24 @@ Route::group(['middleware' => ['web', 'customer'], 'prefix' => 'customer'], func
     ]);
     ]);
 });
 });
 
 
+// API 路由 - 用于前后端分离场景(排除 CSRF 验证,返回 JSON 错误)
+Route::group(['middleware' => ['api', ApiCustomerAuthenticate::class], 'prefix' => 'api/customer'], function () {
+    Route::post('reward-points/sign-in', [
+        'as' => 'api.customer.reward-points.sign-in',
+        'uses' => 'Longyi\RewardPoints\Http\Controllers\RewardPointsController@signIn'
+    ]);
+
+    Route::post('apply-reward-points', [
+        'as' => 'api.checkout.apply-reward-points',
+        'uses' => 'Longyi\RewardPoints\Http\Controllers\RewardPointsController@applyPoints'
+    ]);
+
+    Route::post('remove-reward-points', [
+        'as' => 'api.checkout.remove-reward-points',
+        'uses' => 'Longyi\RewardPoints\Http\Controllers\RewardPointsController@removePoints'
+    ]);
+});
+
 // 后台路由
 // 后台路由
 Route::group(['middleware' => ['web', 'admin'], 'prefix' => 'admin/reward-points'], function () {
 Route::group(['middleware' => ['web', 'admin'], 'prefix' => 'admin/reward-points'], function () {
 
 
@@ -197,3 +216,4 @@ Route::group(['middleware' => ['web', 'admin'], 'prefix' => 'admin/reward-points
         'uses' => 'Longyi\RewardPoints\Http\Controllers\Admin\GrowthValueController@saveSettings'
         'uses' => 'Longyi\RewardPoints\Http\Controllers\Admin\GrowthValueController@saveSettings'
     ]);
     ]);
 });
 });
+