Installation
composer require jdewit/stripe-bundle
Enable the bundle in AppKernel.php:
new Avro\StripeBundle\AvroStripeBundle(),
Configure Stripe Keys
Add to config.yml:
avro_stripe:
client_id: %stripe_client_id%
secret_key: %stripe_secret_key%
publishable_key: %stripe_publishable_key%
Extend User Model
Add Stripe fields to your User entity (e.g., stripeCustomerId, plan).
Example:
use Avro\StripeBundle\Document\Plan;
/**
* @ODM\ReferenceOne(targetDocument="Avro\StripeBundle\Document\Plan")
*/
protected $plan;
Import Routing
Add to routing.yml:
avro_stripe:
resource: "@AvroStripeBundle/Resources/config/routing/routing.yml"
Create a Plan
Extend the base Plan class (e.g., Application\StripeBundle\Document\Plan):
class Plan extends BasePlan { /* Custom logic */ }
Run Schema Update
php app/console doctrine:mongodb:schema:create --index
Use the StripeManager service to create a subscription:
$stripeManager = $this->get('avro_stripe.manager');
$user = $this->getUser(); // FOSUser user
$plan = $stripeManager->findPlanById('monthly_plan_id'); // Your Stripe Plan ID
// Subscribe the user
$subscription = $stripeManager->subscribe($user, $plan);
// Redirect to payment page (handled by bundle routes)
return $this->redirect($this->generateUrl('avro_stripe_customer_new'));
avro_stripe_customer_new route to render the Stripe checkout form.getStripeConnectionParameters() in your User model./stripe/hook.avro_stripe.charge.succeeded) to update your database:
// services.yml
avro_stripe.listener.charge_succeeded:
class: AppBundle\EventListener\StripeChargeListener
tags:
- { name: kernel.event_listener, event: avro_stripe.charge.succeeded, method: onChargeSucceeded }
use Avro\StripeBundle\Event\ChargeEvent;
class StripeChargeListener
{
public function onChargeSucceeded(ChargeEvent $event)
{
$charge = $event->getCharge();
$user = $this->getUserByStripeId($charge->customer);
$user->setIsStripeCustomerActive(true);
$user->getManager()->persist($user);
}
}
Extend the base Plan class and sync with Stripe:
$plan = new Application\StripeBundle\Document\Plan();
$plan->setId('premium_plan');
$plan->setAmount(2999); // $29.99
$plan->setInterval('month');
$plan->setCurrency('usd');
$plan->setName('Premium Monthly');
$stripeManager = $this->get('avro_stripe.manager');
$stripeManager->createPlan($plan);
$user = $this->getUser();
$newPlan = $stripeManager->findPlanById('premium_plan_id');
$stripeManager->updateSubscription($user, $newPlan);
Generate and send invoices via the StripeManager:
$invoice = $stripeManager->getInvoice($user->getStripeCustomerId(), 'in_123');
$pdf = $stripeManager->generateInvoicePdf($invoice);
return new Response($pdf, 200, ['Content-Type' => 'application/pdf']);
avro_stripe_customer_update route to let users update payment methods./stripe/customer/update after login:
return $this->redirect($this->generateUrl('avro_stripe_customer_update'));
Webhook Verification
hook controller:
use Stripe\Webhook;
public function hookAction(Request $request)
{
$payload = $request->getContent();
$sigHeader = $request->headers->get('stripe-signature');
$event = Webhook::constructEvent($payload, $sigHeader, $this->getParameter('stripe_webhook_secret'));
// Dispatch event...
}
MongoDB Indexes
doctrine:mongodb:schema:create --index will cause slow queries on Plan and User collections.Plan ID Mismatch
plan.id as the Doctrine Plan entity’s @ODM\Id. Ensure IDs match exactly (case-sensitive).Hooks Not Triggering
hooks_enabled: false in config.yml, events won’t dispatch. Enable with:
avro_stripe:
hooks_enabled: true
Proration Issues
prorate: true in config.yml to handle partial-period charges when updating plans:
avro_stripe:
prorate: true
Log Stripe Events Add a listener to log all events for debugging:
public function onStripeEvent(StripeEvent $event)
{
$this->logger->debug('Stripe Event:', ['type' => $event->getType(), 'data' => $event->getData()]);
}
Test Webhooks Locally Use Stripe CLI to simulate webhooks:
stripe listen --forward-to localhost:8000/stripe/hook
Check Stripe Dashboard Verify charges/subscriptions in the Stripe Dashboard during development.
Custom Plan Logic
Override Application\StripeBundle\Document\Plan to add business rules (e.g., usage limits):
public function isOverLimit(User $user)
{
return $user->getApiUsage() > $this->getLimit();
}
Custom Hooks Extend the bundle’s event system by creating your own listeners:
// src/AppBundle/EventListener/CustomStripeListener.php
class CustomStripeListener
{
public function onSubscriptionUpdated(SubscriptionEvent $event)
{
// Send Slack notification, etc.
}
}
Override Templates
The bundle uses Twig templates for checkout/invoice pages. Override them in app/Resources/AvroStripeBundle/views/:
app/
└── Resources/
└── AvroStripeBundle/
├── views/
│ ├── Customer/
│ │ └── new.html.twig # Override checkout form
│ └── Invoice/
│ └── show.html.twig # Override invoice template
Add Custom Fields to Users
Extend the getStripeConnectionParameters() method to include additional user data:
public function getStripeConnectionParameters()
{
return [
'stripe_user[email]' => $this->getEmail(),
'stripe_user[custom_field]' => $this->getCustomField(),
];
}
Redirect Routes
Customize redirect routes in config.yml:
avro_stripe:
redirect_routes:
customer_new: app_custom_checkout
subscription_update: app_subscription_success
Translations
The bundle uses Symfony’s translator for emails/invoices. Ensure framework.translator is enabled:
framework:
translator: { fallbacks: ["%locale%"] }
How can I help you explore Laravel packages today?