argument('count'), FILTER_VALIDATE_INT); if ($count === false || $count < 1) { $this->error('Count must be a positive integer.'); return self::FAILURE; } $couponId = (string) $this->option('coupon'); $generatedCodes = []; $rows = []; $this->info("Generating {$count} single-use promotion codes for coupon {$couponId}..."); for ($index = 1; $index <= $count; $index++) { try { $promotionCode = $this->createPromotionCode($couponId, $generatedCodes); } catch (ApiErrorException $exception) { $this->error("Failed generating promotion code {$index}: {$exception->getMessage()}"); return self::FAILURE; } $generatedCodes[] = $promotionCode->code; $rows[] = [$index, $promotionCode->id, $promotionCode->code]; } $this->newLine(); $this->table(['#', 'Stripe ID', 'Code'], $rows); $this->newLine(); $this->info('Generated '.$count.' promotion code'.($count === 1 ? '' : 's').'.'); return self::SUCCESS; } /** * @param list $generatedCodes */ private function createPromotionCode(string $couponId, array $generatedCodes): PromotionCode { for ($attempt = 1; $attempt <= 5; $attempt++) { $code = $this->makeCode($generatedCodes); try { return Cashier::stripe()->promotionCodes->create([ 'coupon' => $couponId, 'code' => $code, 'max_redemptions' => 1, ]); } catch (ApiErrorException $exception) { if ($attempt < 5 && $this->isDuplicateCodeError($exception)) { continue; } throw $exception; } } throw new RuntimeException('Unable to generate a unique promotion code after 5 attempts.'); } /** * @param list $generatedCodes */ private function makeCode(array $generatedCodes): string { do { $code = 'WM-'.Str::upper(Str::random(10)); } while (in_array($code, $generatedCodes, true)); return $code; } private function isDuplicateCodeError(ApiErrorException $exception): bool { $message = Str::lower($exception->getMessage()); return str_contains($message, 'code') && str_contains($message, 'exist'); } }