price_arm : $cookieArm) ?? self::LEGACY; } /** * The plans config with the request's arm applied: price, original_price and * Stripe lookup key. Feeds both the shared pricing prop and checkout, so what * is shown is always what is charged. * * @return array> */ public static function plansFor(?User $user, ?string $cookieArm = null): array { $plans = (array) config('subscriptions.plans', []); $arm = self::armFor($user, $cookieArm); $overrides = (array) config("subscriptions.price_experiment.variants.{$arm}", []); foreach ($overrides as $planKey => $override) { if (! isset($plans[$planKey])) { continue; } $plans[$planKey]['price'] = $override['price']; $plans[$planKey]['original_price'] = $override['original_price'] ?? null; $plans[$planKey]['stripe_lookup_key'] = $override['lookup']; } return $plans; } /** * Stripe lookup key to charge for a plan, resolved from the user's stored arm * server-side and never from the request, so nobody can pick the cheap price * by editing their cookie after signing up. */ public static function lookupKeyFor(User $user, string $planKey): string { return (string) (self::plansFor($user)[$planKey]['stripe_lookup_key'] ?? ''); } /** * The winner pinned via PRICE_EXPERIMENT_FORCE_VARIANT, applied to everyone — * visitors and existing users — so a rollout needs no deploy and no backfill. */ private static function forcedArm(): ?string { return self::sanitize(config('subscriptions.price_experiment.force_variant')); } }