Weave 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

Payment Bundle Laravel Package

akyos/payment-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require akyos/payment-bundle
    

    Add the bundle to config/bundles.php:

    return [
        // ...
        Akyos\PaymentBundle\AkyosPaymentBundle::class => ['all' => true],
    ];
    
  2. Configuration Publish the default config:

    php bin/console config:dump-reference Akyos\PaymentBundle\DependencyInjection\Configuration
    

    Configure Stripe keys in .env:

    STRIPE_SECRET_KEY=your_secret_key
    STRIPE_PUBLISHABLE_KEY=your_publishable_key
    
  3. First Use Case: Creating a Payment Intent Inject the PaymentService in a controller:

    use Akyos\PaymentBundle\Service\PaymentService;
    
    class CheckoutController extends AbstractController
    {
        public function __construct(private PaymentService $paymentService) {}
    
        public function createIntent(Request $request): JsonResponse
        {
            $intent = $this->paymentService->createPaymentIntent(
                $request->request->get('amount'),
                $request->request->get('currency', 'usd')
            );
            return $this->json($intent);
        }
    }
    
  4. Frontend Integration Use the publishable key in your frontend (e.g., React/Vue) to initialize Stripe.js:

    const stripe = Stripe(process.env.STRIPE_PUBLISHABLE_KEY);
    

Implementation Patterns

Core Workflows

  1. Payment Creation Use PaymentService for server-side payment logic:

    $intent = $paymentService->createPaymentIntent(1000, 'usd'); // $10.00
    $intent = $paymentService->createPaymentIntent(1000, 'usd', ['metadata' => ['order_id' => 123]]);
    
  2. Webhook Handling Register a controller to handle Stripe webhooks:

    #[Route('/stripe/webhook', name: 'stripe_webhook', methods: ['POST'])]
    public function handleWebhook(Request $request, PaymentService $paymentService): Response
    {
        $event = $paymentService->handleWebhook($request->getContent());
        // Process event (e.g., update order status)
        return new Response('OK');
    }
    
  3. Subscription Management Create/subscribe customers:

    $customer = $paymentService->createCustomer('[email protected]', 'card_123');
    $subscription = $paymentService->createSubscription($customer->id, 'price_123');
    
  4. Refunds and Disputes Handle refunds via:

    $paymentService->createRefund('pi_123', ['amount' => 500]); // Refund $5.00
    

Integration Tips

  1. Dependency Injection Prefer constructor injection for PaymentService in controllers/services:

    public function __construct(private PaymentService $paymentService) {}
    
  2. Event Listeners Extend functionality by listening to Stripe events:

    #[AsEventListener(event: KernelEvents::TERMINATE)]
    public function onKernelTerminate(Request $request, PaymentService $paymentService)
    {
        if ($request->getPathInfo() === '/stripe/webhook') {
            $paymentService->handleWebhook($request->getContent());
        }
    }
    
  3. Testing Use Stripe test keys (pk_test_..., sk_test_...) and mock the service in tests:

    $this->paymentService = $this->createMock(PaymentService::class);
    $this->paymentService->method('createPaymentIntent')
        ->willReturn(['client_secret' => 'test_secret']);
    
  4. Configuration Overrides Override default config in config/packages/akyos_payment.yaml:

    akyos_payment:
        stripe:
            webhook_secret: 'whsec_...' # Optional: Validate webhook signatures
    

Gotchas and Tips

Pitfalls

  1. Webhook Validation

    • Without webhook_secret in config, webhook events will not be validated. Always set it in production:
      akyos_payment:
          stripe:
              webhook_secret: '%env(STRIPE_WEBHOOK_SECRET)%'
      
  2. Amount Handling

    • Stripe expects amounts in smallest currency units (e.g., cents for USD). Ensure your app converts dollars to cents:
      $amountInCents = $amountInDollars * 100;
      
  3. Customer ID Persistence

    • Store Stripe customer IDs in your database (e.g., users table) to avoid recreating customers on every payment.
  4. Idempotency Keys

    • Always use idempotency keys for idempotent operations (e.g., creating payment intents):
      $intent = $paymentService->createPaymentIntent(1000, 'usd', [], 'unique_key_123');
      
  5. Error Handling

    • Stripe errors are thrown as exceptions. Catch Stripe\Exception\BaseException globally or per-operation:
      try {
          $intent = $paymentService->createPaymentIntent(1000, 'usd');
      } catch (Stripe\Exception\CardException $e) {
          // Handle card errors
      }
      

Debugging Tips

  1. Log Stripe Events Enable logging in config/packages/akyos_payment.yaml:

    akyos_payment:
        debug: true # Logs all Stripe API calls/responses
    
  2. Stripe CLI Use the Stripe CLI to test webhooks locally:

    stripe listen --forward-to localhost:8000/stripe/webhook
    
  3. Test Mode Quirks

    • Test cards (e.g., 4242 4242 4242 4242) work in test mode but fail in live mode.
    • Use stripe test helpers to simulate 3D Secure or failed payments.

Extension Points

  1. Custom Services Extend PaymentService to add domain-specific logic:

    class CustomPaymentService extends PaymentService
    {
        public function createOrderPayment(int $orderId, float $amount): array
        {
            $intent = parent::createPaymentIntent($amount * 100, 'usd');
            // Add order metadata
            $intent['metadata']['order_id'] = $orderId;
            return $intent;
        }
    }
    
  2. Event Dispatching Dispatch Symfony events after payment operations:

    $paymentService->createPaymentIntent(1000, 'usd', [], null, function ($intent) {
        $this->eventDispatcher->dispatch(new PaymentIntentCreatedEvent($intent));
    });
    
  3. Custom Webhook Handlers Override the default webhook handler:

    $paymentService->setWebhookHandler(function ($event) {
        // Custom logic for specific event types
        if ($event->type === 'payment_intent.succeeded') {
            // Update order status
        }
    });
    
  4. Rector for Upgrades The bundle includes Rector for PHP 8.1+ migrations. Run it during upgrades:

    vendor/bin/rector process src --dry-run
    
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.
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names