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

Laravel Payments Laravel Package

mdiqbal/laravel-payments

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require mdiqbal/laravel-payments
    php artisan vendor:publish --provider="MDIqbal\LaravelPayments\LaravelPaymentsServiceProvider" --tag="config"
    

    Publish migrations and run:

    php artisan migrate
    
  2. Configure Edit .env with your preferred gateway credentials (e.g., STRIPE_SECRET_KEY or PAYPAL_CLIENT_ID). Update config/payments.php to set default gateway and preferences.

  3. First Use Case Process a payment in a controller:

    use MDIqbal\LaravelPayments\Facades\Payment;
    
    $payment = Payment::gateway('stripe')
        ->amount(1000) // $10.00
        ->currency('USD')
        ->method('card')
        ->pay();
    

Where to Look First

  • Config File: config/payments.php (default gateway, supported gateways, settings).
  • Gateway Docs: Check the README’s Gateway Documentation for provider-specific quirks (e.g., PayPal’s capture vs. authorize).
  • Webhooks: Review routes/web.php for pre-configured webhook routes (e.g., payment/webhook/stripe).

Implementation Patterns

Unified Workflow

  1. Gateway Selection Dynamically switch gateways based on user location, preferences, or business logic:

    $gateway = request()->input('gateway') ?? config('payments.default');
    $payment = Payment::gateway($gateway)->process();
    
  2. Payment Processing Create Intent (for Stripe, PayPal, etc.):

    $intent = Payment::gateway('stripe')
        ->amount(5000)
        ->currency('USD')
        ->method('card')
        ->createIntent();
    

    Return the client_secret to frontend for payment confirmation.

    Handle Callback:

    public function handleCallback(Request $request) {
        $payment = Payment::gateway('paypal')
            ->verify($request->all());
        if ($payment->success()) {
            // Fulfill order
        }
    }
    
  3. Subscription Management

    // Stripe example
    $subscription = Payment::gateway('stripe')
        ->customer('cus_123')
        ->plan('monthly_plan')
        ->createSubscription();
    
  4. Refunds/Voids

    $refund = Payment::gateway('paystack')
        ->transaction('txn_123')
        ->refund(500); // Partial refund
    

Integration Tips

  • Frontend Integration: Use the createIntent() method to generate tokens/secrets (e.g., Stripe’s PaymentIntent or PayPal’s Order ID). Pass these to frontend libraries (e.g., Stripe.js, PayPal.js) for seamless checkout.

    // Example for Stripe
    const { error, paymentIntent } = await stripe.confirmCardPayment(clientSecret, {
        payment_method: { card: elements.getElement(CardElement) }
    });
    
  • Order Workflow: Tie payments to Eloquent models using payment_data or metadata:

    $payment = Payment::gateway('razorpay')
        ->amount(2000)
        ->currency('INR')
        ->metadata(['order_id' => $order->id])
        ->pay();
    
  • Webhooks: Validate webhooks using the verify() method. Log unhandled events for debugging:

    public function stripeWebhook(Request $request) {
        $event = Payment::gateway('stripe')->verifyWebhook($request->getContent());
        // Handle event (e.g., payment_succeeded, charge.refunded)
    }
    
  • Fallback Logic: Implement a fallback to another gateway if the primary fails:

    try {
        $payment = Payment::gateway('paypal')->pay();
    } catch (\Exception $e) {
        $payment = Payment::gateway('stripe')->pay();
    }
    

Gotchas and Tips

Pitfalls

  1. Gateway-Specific Quirks:

    • PayPal: Uses capture() for immediate funds and authorize() for holds. Ensure your flow matches the provider’s requirements.
    • Razorpay: Requires email and contact for customers. Missing these may cause failures.
    • SSLCommerz: Needs store_id, store_passwd, and total_amount in a specific format. Validate against their API docs.
    • bKash: Requires a merchant_invoice_number (use metadata or a UUID).
  2. Webhook Validation:

    • Always verify webhook signatures (e.g., Stripe’s stripe-signature header). Use the verifyWebhook() method to avoid replay attacks.
    • Log unhandled webhook events to debug issues:
      \Log::debug('Unhandled webhook event:', $event->toArray());
      
  3. Currency/Amount Handling:

    • Ensure amounts are in the smallest currency unit (e.g., cents for USD, paise for INR). Use amount() in cents, not dollars.
    • Some gateways (e.g., Paystack) require amounts in kobo (1 NGN = 100 kobo). Convert manually if needed.
  4. Testing:

    • Use sandbox/test modes for all gateways (configured in .env). Example:
      STRIPE_SECRET_KEY=sk_test_...
      PAYPAL_MODE=sandbox
      
    • Mock webhooks in tests:
      $this->postJson('/payment/webhook/stripe', $payload)
          ->assertSuccessful();
      
  5. Rate Limiting:

    • Some gateways (e.g., PayPal) throttle requests. Implement retries with exponential backoff for idempotent operations:
      use MDIqbal\LaravelPayments\Exceptions\PaymentException;
      
      try {
          $payment = Payment::gateway('paypal')->pay();
      } catch (PaymentException $e) {
          if ($e->isRetryable()) {
              retry()->times(3)->try(fn() => Payment::gateway('paypal')->pay());
          }
      }
      

Debugging Tips

  1. Enable Logging: Add to config/payments.php:

    'log' => [
        'enabled' => true,
        'channel' => 'single',
    ],
    

    Check logs for gateway responses/errors.

  2. Inspect Raw Responses: Use ->getRawResponse() to debug API responses:

    $response = Payment::gateway('stripe')->createIntent()->getRawResponse();
    \Log::info('Stripe response:', $response);
    
  3. Common Errors:

    • Invalid amount: Check currency unit (e.g., USD = cents, INR = paise).
    • Missing parameter: Validate required fields (e.g., email for Razorpay).
    • Signature verification failed: Ensure webhook secrets match .env.
    • Gateway not found: Verify the gateway name in config/payments.php under supported_gateways.

Extension Points

  1. Add a New Gateway:

    • Create a service class extending MDIqbal\LaravelPayments\Contracts\Gateway.
    • Register it in config/payments.php:
      'supported_gateways' => [
          'custom_gateway' => \App\Services\CustomGateway::class,
      ],
      
    • Implement createIntent(), verify(), and refund() methods.
  2. Customize Payment Data: Extend the Payment facade to add methods:

    // app/Providers/AppServiceProvider.php
    Payment::macro('customMethod', function () {
        return $this->getGateway()->customLogic();
    });
    
  3. Override Default Config: Publish the config and modify:

    php artisan vendor:publish --tag="payments-config"
    

    Update config/payments.php to change default behavior (e.g., timeout, retry logic).

  4. Webhook Handlers: Extend the WebhookHandler class to add custom logic for specific events:

    namespace App\Services;
    
    use MDIqbal\LaravelPayments\Handlers\WebhookHandler as BaseHandler;
    
    class CustomWebhookHandler extends BaseHandler {
        public function handlePaymentSucceeded($payload) {
            // Custom logic
        }
    }
    

    Bind it in AppServiceProvider:

    Payment::setWebhookHandler(CustomWebhookHandler::class);
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours