jonpurvis/faker-stripe
A Faker extension for generating realistic fake Stripe data—customer, payment intent, subscription, and other object IDs—so you can seed test databases and write fixtures without calling the Stripe API.
The package is a FakerPHP provider — it adds methods to Faker that return string IDs shaped like real Stripe object IDs (cus_…, pi_…, sub_…, evt_…, ch_…, in_…, price_…, prod_…, pm_…, po_…, acct_…, tdsa_…, etc.). It does not produce Stripe objects, only IDs.
Minimal setup:
composer require jonpurvis/faker-stripe --dev
Register the provider on the Faker generator. In a Laravel app, the cleanest place is AppServiceProvider::register() so it applies everywhere Faker is resolved (factories, seeders, tests):
use Faker\Generator;
use JonPurvis\FakerStripe\StripeProvider;
public function register(): void
{
$this->app->afterResolving(Generator::class, function (Generator $faker) {
$faker->addProvider(new StripeProvider($faker));
});
}
Then use it in a factory:
public function definition(): array
{
return [
'stripe_id' => fake()->stripeCustomerId(),
// ...
];
}
Where to look first: the README on GitHub for the full method list — it changes over time, and stripeCustomerId, stripePaymentIntentId, stripeSubscriptionId, stripeEventId, stripePriceId, stripeProductId, stripePaymentMethodId, stripeInvoiceId, and stripeChargeId are the ones you will reach for most. Skim the provider class itself if you need an exhaustive list. As of v5.5.0 there is also a 3D Secure authentication ID generator (tdsa_…) — see the provider class for the exact method name in your installed version.
First use case that pays for itself immediately: replacing 'cus_' . Str::random(14) hand-rolled strings in Cashier model factories with fake()->stripeCustomerId(), so the test data reads like real Stripe data and matches whatever string-length validation your app layers on.
Cashier / Billable model factories. The most common day-to-day use. A User or Team factory that has a stripe_id column:
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'stripe_id' => fake()->stripeCustomerId(),
'pm_type' => 'visa',
'pm_last_four' => fake()->numerify('####'),
'trial_ends_at' => null,
];
}
Related-resource factories. A Subscription or Invoice model that references a customer and a price:
public function definition(): array
{
return [
'user_id' => User::factory(),
'type' => 'default',
'stripe_id' => fake()->stripeSubscriptionId(),
'stripe_status' => 'active',
'stripe_price' => fake()->stripePriceId(),
'quantity' => 1,
];
}
Webhook fixture building. When you Http::fake() a Stripe webhook test, the payload needs IDs that look like they came from Stripe so any DTO/casting code paths run cleanly:
Http::fake();
$event = [
'id' => fake()->stripeEventId(),
'type' => 'customer.subscription.updated',
'data' => [
'object' => [
'id' => fake()->stripeSubscriptionId(),
'customer' => $user->stripe_id,
'status' => 'active',
],
],
];
SCA / 3DS flows (new in v5.5.0). If your app branches on PaymentIntent.next_action.type === 'use_stripe_sdk' or stores the outcome of a 3DS challenge, the tdsa_… generator gives you a plausible authentication ID for those fixtures:
$authentication = [
'id' => fake()->stripe3dSecureAuthenticationId(), // check provider for exact name
'type' => 'three_d_secure',
'result' => 'authenticated',
];
$intent = [
'id' => fake()->stripePaymentIntentId(),
'status' => 'requires_action',
'next_action' => ['type' => 'use_stripe_sdk'],
'authentication' => $authentication,
];
Combine with your existing payload helper so the 3DS branch is exercised in at least one feature test, not just the happy path.
Shared test bootstrap. Register the provider once in tests/TestCase.php::setUp() (or a Pest beforeEach) if you prefer not to touch AppServiceProvider. Just pick one — running both is redundant.
protected function setUp(): void
{
parent::setUp();
fake()->addProvider(new \JonPurvis\FakerStripe\StripeProvider(fake()));
}
Composite helper for complex objects. If a test needs a realistic Stripe PaymentIntent array, wrap the ID calls in a small test helper (StripePayload::paymentIntent()). This keeps the raw ID-generation noise out of test bodies and gives you one place to evolve when the Stripe API shape changes.
Datasets for edge cases. Because the methods just return strings, they compose well with Pest datasets — e.g. ->with([fake()->stripeSubscriptionId(), fake()->stripeCustomerId()]) — as long as you generate those values before the test closure, not inside it.
addProvider does not deduplicate. Calling it in both AppServiceProvider and TestCase::setUp() will register the provider twice, growing the generator's method-resolution chain. In long-running test suites (or Octane-based test runners) this is a slow leak. Register in exactly one place.strlen($id) === 27 or that the suffix is exactly 24 characters — Stripe has varied ID shapes over time and the provider will track that. Assert str_starts_with($id, 'cus_') if you need anything at all.stripe-mock if you need whole-object fidelity. Do not expect the provider to return a PaymentIntent shape — the new tdsa_ ID is likewise just a string, not a 3DS session.--dev dependency and the IDs are meaningless to Stripe. Using it in a real seeder that later tries to reconcile accounts will produce dead references.unique() wrapper. If your stripe_id column has a unique index and you are seeding hundreds of rows, wrap it: fake()->unique()->stripeCustomerId(). Collisions are astronomically unlikely but Faker's unique() makes the intent explicit and retries safely.StripeProvider and add a method that calls the same underlying prefix+suffix generator, or open an issue upstream — the maintainer is responsive and additions are trivial to merge.get_class_methods(\JonPurvis\FakerStripe\StripeProvider::class) in php artisan tinker is the fastest way to see exactly what is available in the version you installed, especially if the README has drifted. This matters more now that releases are adding single methods (v5.5.0 added the tdsa_ generator) between minor bumps — run composer update jonpurvis/faker-stripe and check before reaching for a method from a blog post.require-dev package, any code that calls stripeCustomerId() in app/ will break in production. Keep the calls confined to factories, seeders, and tests/ — or guard with app()->environment('testing') if you must.How can I help you explore Laravel packages today?