Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cashier Braintree Laravel Package

laravel/cashier-braintree

Laravel Cashier driver for Braintree: a simple subscription billing integration for Laravel apps. Manage customers, plans, subscriptions, coupons/discounts, and webhooks with an expressive API built on top of the Braintree PHP SDK.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laravel/cashier-braintree
    

    Ensure braintree/braintree_php is also installed (dependency).

  2. Configuration: Publish the config file:

    php artisan vendor:publish --provider="Laravel\Cashier\CashierServiceProvider"
    

    Update .env with Braintree credentials:

    BRAINTREE_MERCHANT_ID=your_merchant_id
    BRAINTREE_PUBLIC_KEY=your_public_key
    BRAINTREE_PRIVATE_KEY=your_private_key
    
  3. First Use Case: Subscribe a user in a controller:

    use Laravel\Cashier\Cashier;
    use App\Models\User;
    
    $user = User::find(1);
    $user->newSubscription('main', 'price_id_from_braintree')
         ->create($paymentMethodId);
    

Key Files to Review

  • config/cashier.php: Gateway settings, webhook handling.
  • app/Models/User.php: Ensure HasSubscriptions trait is used.
  • routes/web.php: Webhook routes for Braintree events (e.g., braintree.webhook).

Implementation Patterns

Core Workflows

  1. Subscription Management:

    • Create:
      $user->newSubscription('main', 'braintree_price_id')
           ->quantity(2) // Optional
           ->trialDays(7) // Optional
           ->create($paymentMethodId);
      
    • Cancel/Suspend:
      $user->subscription('main')->cancel(); // Immediate
      $user->subscription('main')->suspend(); // Grace period
      
    • Resume/Reactivate:
      $user->subscription('main')->resume();
      
  2. Payment Handling:

    • Process Payment:
      $user->charge(1000); // 10.00 USD
      
    • Update Payment Method:
      $user->updateDefaultPaymentMethod($newPaymentMethodId);
      
  3. Webhooks:

    • Define routes in routes/web.php:
      Route::post('/braintree/webhook', [WebhookController::class, 'handleWebhook']);
      
    • Handle events in WebhookController:
      public function handleWebhook(Request $request) {
          $payload = $request->getContent();
          event(new BraintreeWebhookReceived($payload));
      }
      
  4. Billing Portal:

    • Redirect users to Braintree’s portal:
      $portalUrl = $user->subscription('main')->portalUrl();
      return redirect()->away($portalUrl);
      

Integration Tips

  • Sync with Braintree: Use sync() to ensure local subscriptions match Braintree’s state:
    $user->subscriptions()->sync();
    
  • Custom Fields: Attach metadata to subscriptions:
    $user->newSubscription('main', 'price_id')
         ->withMetadata(['plan' => 'premium'])
         ->create($paymentMethodId);
    
  • Testing: Use Braintree’s sandbox environment (configured in .env):
    BRAINTREE_ENVIRONMENT=sandbox
    

Gotchas and Tips

Pitfalls

  1. Webhook Delays:

    • Braintree may retry webhook deliveries. Use idempotency keys in your handler to avoid duplicate processing.
    • Example:
      public function handleWebhook(Request $request) {
          $payload = $request->getContent();
          $event = Braintree_WebhookParser::parse($payload);
      
          if ($event->type === 'subscription_charged') {
              $user = User::find($event->subscription->customer->id);
              $user->syncSubscriptions();
          }
      }
      
  2. Subscription Sync Issues:

    • Call sync() after manual operations (e.g., canceling via Braintree dashboard) to avoid state mismatches.
    • Use fresh() to reload the subscription model if stale data is suspected.
  3. Price ID Mismatches:

    • Ensure price_id in Laravel matches Braintree’s id (not plan_id or product_id). Verify via Braintree’s Customer Portal.
  4. Payment Method Validation:

    • Always validate payment methods before charging:
      if (!$user->hasValidPaymentMethod()) {
          return redirect()->route('payment.methods');
      }
      

Debugging Tips

  • Log Webhook Payloads: Add logging to handleWebhook for troubleshooting:
    \Log::debug('Braintree Webhook', ['payload' => $payload]);
    
  • Braintree Test Mode: Use Braintree’s test credit cards for sandbox testing:
    4111 1111 1111 1111 (Visa)
    5555 5555 5555 4444 (MasterCard)
    

Extension Points

  1. Custom Events: Listen for Cashier events (e.g., illuminate.auth.events.SubscriptionCreated):
    Event::listen(SubscriptionCreated::class, function ($user, $subscription) {
        // Send welcome email
    });
    
  2. Gateway Extensions: Override default behavior by extending Laravel\Cashier\Cashier or using middleware:
    public function createSubscription($name, $plan, $options = []) {
        // Custom logic before creating subscription
        return parent::createSubscription($name, $plan, $options);
    }
    
  3. Webhook Middleware: Add middleware to validate signatures or transform payloads:
    Route::post('/braintree/webhook', function (Request $request) {
        $request->merge(['payload' => Braintree_WebhookParser::parse($request->getContent())]);
        return $this->handleWebhook($request);
    })->middleware('validate.braintree.signature');
    

Config Quirks

  • Environment Switching: Ensure BRAINTREE_ENVIRONMENT in .env matches your Braintree account (e.g., sandbox vs. production).
  • Webhook Signing: Enable webhook signing in Braintree’s control panel and configure webhook_signing_secret in config/cashier.php:
    'webhook_signing_secret' => env('BRAINTREE_WEBHOOK_SIGNING_SECRET'),
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport