Customers
The bundle persists a local projection of the Stripe customer in CashierBundle\Entity\StripeCustomer.
Create or retrieve a Stripe customer
use CashierBundle\Contract\BillableEntityInterface;
use CashierBundle\Service\CustomerService;
final readonly class CheckoutController
{
public function __construct(
private CustomerService $customerService,
) {
}
public function __invoke(BillableEntityInterface $user): void
{
$stripeId = $this->customerService->createOrGetStripeId($user);
}
}The Stripe payload is built from your billable entity:
getEmail()getName()getPhone(): ?string(optional)getAddress(): ?array(optional, must return['line1' => '...', 'line2' => '...', 'postal_code' => '...', 'city' => '...', 'country' => 'FR'])
Update the customer
$this->customerService->update($user, [
'metadata' => [
'source' => 'backoffice',
],
]);Local synchronization
The bundle keeps useful data locally to avoid depending solely on a real-time Stripe fetch.
Automatically synchronized fields
Fields of StripeCustomer:
stripeIdemailnamephonecurrencybalance(balance in cents)address(array)invoicePrefixtaxExemptpmType(default payment method type)pmLastFour(last 4 digits)billableIdbillableType
Synchronization from Stripe
To synchronize data from Stripe (useful in a customer.updated webhook handler):
$this->customerService->sync($user); // synchronizes from the local entity
$this->customerService->syncByStripeId('cus_xxx'); // synchronizes from Stripe APIDeletion
When a customer is deleted in Stripe, the customer.deleted webhook triggers CustomerDeletedHandler which deletes the local StripeCustomer (not the application User entity).
Balance
The bundle manages the Stripe customer balance (credits/debits).
// Credit the balance (negative amount at Stripe, in cents)
$user->creditBalance(1000, 'Bonus credit'); // 10€
// Debit the balance
$user->debitBalance(500, 'Service usage');
// Formatted balance
$user->balance(); // string, e.g. "10.00 EUR"CustomerBalanceTransaction
Each balance operation is persisted in CashierBundle\Entity\CustomerBalanceTransaction:
id— unique IDamount— amount in cents (negative = credit, positive = debit)currency— currencytype— transaction typedescription— descriptionisCredit()— returnstrueif creditisDebit()— returnstrueif debit
Customer locale
For invoices, the locale follows this priority:
- explicit locale passed to rendering
preferred_localesof the Stripe customercashier.invoices.default_locale
If your application already knows the user’s language, push it to Stripe via preferred_locales at checkout or when updating the customer.