|
|
@@ -419,6 +419,141 @@ class RewardPointsController extends Controller
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 支持的关注平台
|
|
|
+ */
|
|
|
+ const FOLLOW_PLATFORMS = ['ig' => 'Instagram', 'fb' => 'Facebook', 'ytb' => 'YouTube', 'tt' => 'TikTok'];
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关注社交平台赠送积分(每位用户每个平台仅一次,永久有效)
|
|
|
+ *
|
|
|
+ * @param Request $request
|
|
|
+ * @return \Illuminate\Http\JsonResponse
|
|
|
+ */
|
|
|
+ public function followPlatform(Request $request)
|
|
|
+ {
|
|
|
+ $customer = auth()->guard('customer')->user();
|
|
|
+
|
|
|
+ if (!$customer) {
|
|
|
+ return ApiResponse::unauthorized();
|
|
|
+ }
|
|
|
+
|
|
|
+ $platform = $request->input('platform');
|
|
|
+
|
|
|
+ if (!$platform || !isset(self::FOLLOW_PLATFORMS[$platform])) {
|
|
|
+ return ApiResponse::validationError('Invalid platform. Supported: ' . implode(', ', array_keys(self::FOLLOW_PLATFORMS)));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Redis Key: follow_platform:{customer_id}:{platform}(永久有效,不设 TTL)
|
|
|
+ $redisKey = "follow_platform:{$customer->id}:{$platform}";
|
|
|
+
|
|
|
+ // 1. Redis 快速判断(主缓存)
|
|
|
+ if (Redis::exists($redisKey)) {
|
|
|
+ return ApiResponse::error('You have already earned points for following ' . self::FOLLOW_PLATFORMS[$platform]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. DB 兜底检查:防止 Redis 被清理后重复发积分
|
|
|
+ $dbExists = RewardPointHistory::where('customer_id', $customer->id)
|
|
|
+ ->where('type_of_transaction', RewardActiveRule::TYPE_FOLLOW)
|
|
|
+ ->where('transaction_detail', 'Followed ' . self::FOLLOW_PLATFORMS[$platform])
|
|
|
+ ->exists();
|
|
|
+
|
|
|
+ if ($dbExists) {
|
|
|
+ // DB 有记录但 Redis 丢失,回补 Redis
|
|
|
+ Redis::set($redisKey, 1);
|
|
|
+ return ApiResponse::error('You have already earned points for following ' . self::FOLLOW_PLATFORMS[$platform]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询有效的关注规则
|
|
|
+ $rule = RewardActiveRule::active()
|
|
|
+ ->ofType(RewardActiveRule::TYPE_FOLLOW)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$rule) {
|
|
|
+ return ApiResponse::forbidden('Follow reward is not available');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查规则是否适用于当前客户
|
|
|
+ if (!$rule->isApplicableToCustomer($customer)) {
|
|
|
+ return ApiResponse::forbidden('This reward is not applicable to your account');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取该客户应得的积分
|
|
|
+ $points = $rule->getPointsForCustomer($customer);
|
|
|
+ if ($points <= 0) {
|
|
|
+ $points = (int) $rule->reward_point;
|
|
|
+ }
|
|
|
+ if ($points <= 0) {
|
|
|
+ return ApiResponse::error('No points configured for follow reward');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加积分
|
|
|
+ $this->rewardPointRepository->addPoints(
|
|
|
+ $customer->id,
|
|
|
+ RewardActiveRule::TYPE_FOLLOW,
|
|
|
+ $points,
|
|
|
+ null,
|
|
|
+ 'Followed ' . self::FOLLOW_PLATFORMS[$platform],
|
|
|
+ $rule
|
|
|
+ );
|
|
|
+
|
|
|
+ // 写入 Redis(永久有效,无需 TTL)
|
|
|
+ Redis::set($redisKey, 1);
|
|
|
+
|
|
|
+ $totalPoints = $this->rewardPointRepository->getCustomerPoints($customer->id);
|
|
|
+
|
|
|
+ return ApiResponse::success([
|
|
|
+ 'platform' => $platform,
|
|
|
+ 'platform_name' => self::FOLLOW_PLATFORMS[$platform],
|
|
|
+ 'points' => $points,
|
|
|
+ 'total_points' => $totalPoints
|
|
|
+ ], 'You earned ' . $points . ' points for following ' . self::FOLLOW_PLATFORMS[$platform] . '!');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户已关注的平台列表及积分状态
|
|
|
+ *
|
|
|
+ * @return \Illuminate\Http\JsonResponse
|
|
|
+ */
|
|
|
+ public function getFollowStatus()
|
|
|
+ {
|
|
|
+ $customer = auth()->guard('customer')->user();
|
|
|
+
|
|
|
+ if (!$customer) {
|
|
|
+ return ApiResponse::unauthorized();
|
|
|
+ }
|
|
|
+
|
|
|
+ $platforms = [];
|
|
|
+ foreach (self::FOLLOW_PLATFORMS as $code => $name) {
|
|
|
+ $redisKey = "follow_platform:{$customer->id}:{$code}";
|
|
|
+ $followed = (bool) Redis::exists($redisKey);
|
|
|
+
|
|
|
+ // Redis 未命中时,从 DB 回补并修复 Redis
|
|
|
+ if (!$followed) {
|
|
|
+ $dbExists = RewardPointHistory::where('customer_id', $customer->id)
|
|
|
+ ->where('type_of_transaction', RewardActiveRule::TYPE_FOLLOW)
|
|
|
+ ->where('transaction_detail', 'Followed ' . $name)
|
|
|
+ ->exists();
|
|
|
+
|
|
|
+ if ($dbExists) {
|
|
|
+ Redis::set($redisKey, 1);
|
|
|
+ $followed = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $platforms[] = [
|
|
|
+ 'code' => $code,
|
|
|
+ 'name' => $name,
|
|
|
+ 'followed' => $followed
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ return ApiResponse::success([
|
|
|
+ 'platforms' => $platforms,
|
|
|
+ 'followed_count' => count(array_filter($platforms, fn($p) => $p['followed']))
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Get points information for cart
|
|
|
*/
|