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

Payzephyr Laravel Package

kendenigerian/payzephyr

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require kendenigerian/payzephyr
    php artisan vendor:publish --provider="KenDeNigerian\PayZephyr\PayZephyrServiceProvider" --tag="migrations"
    php artisan migrate
    
  2. Configuration:

    • Publish the config file:
      php artisan vendor:publish --provider="KenDeNigerian\PayZephyr\PayZephyrServiceProvider" --tag="config"
      
    • Update .env with your preferred provider credentials (e.g., PAYSTACK_SECRET_KEY, STRIPE_SECRET_KEY).
    • Configure the providers array in config/payzephyr.php to define the order of fallback providers:
      'providers' => [
          'paystack' => [
              'enabled' => true,
              'priority' => 1,
          ],
          'flutterwave' => [
              'enabled' => false,
              'priority' => 2,
          ],
          // ...
      ],
      
  3. First Use Case:

    • Create a payment intent for a one-time charge:
      use KenDeNigerian\PayZephyr\Facades\PayZephyr;
      
      $payment = PayZephyr::charge(1000, 'USD', [
          'email' => 'customer@example.com',
          'metadata' => ['order_id' => '12345'],
      ]);
      
    • Redirect the customer to the payment URL:
      return redirect()->away($payment->getRedirectUrl());
      
  4. Webhook Setup:

    • Add the webhook route to routes/web.php:
      Route::post('/payzephyr/webhook', [PayZephyrWebhookController::class, 'handleWebhook']);
      
    • Configure webhook endpoints in config/payzephyr.php under webhooks.

Implementation Patterns

Core Workflows

1. Payment Processing

  • One-Time Charges: Use PayZephyr::charge() for ad-hoc payments. The package automatically retries with the next enabled provider if the first fails.

    $payment = PayZephyr::charge(5000, 'NGN', [
        'email' => 'user@example.com',
        'metadata' => ['invoice_id' => 'INV-2023-001'],
    ]);
    
    • Fallback Handling: Configure max_attempts in config/payzephyr.php to control how many providers are tried before failing.
  • Subscription Management: Create subscriptions with PayZephyr::createSubscription():

    $subscription = PayZephyr::createSubscription('monthly_plan', 2999, 'USD', [
        'customer_email' => 'user@example.com',
        'trial_days' => 7,
    ]);
    
    • Subscription Events: Listen to subscription lifecycle events (e.g., subscription.created, invoice.payment_succeeded) via Laravel events or webhooks.
  • Refunds and Cancellations:

    // Refund a payment
    PayZephyr::refund($paymentId, 1000, 'USD');
    
    // Cancel a subscription
    PayZephyr::cancelSubscription($subscriptionId);
    

2. Webhook Handling

  • Automatic Validation: The package validates webhook signatures and replay attacks out of the box. Extend the PayZephyrWebhookController to handle provider-specific events:
    public function handleWebhook(Request $request)
    {
        $event = PayZephyr::handleWebhook($request);
    
        switch ($event->type) {
            case 'invoice.payment_succeeded':
                // Handle successful payment
                break;
            case 'subscription.updated':
                // Handle subscription changes
                break;
        }
    }
    
  • Custom Logic: Dispatch Laravel events or queue jobs based on webhook events for async processing.

3. Provider-Specific Customization

  • Override Default Behavior: Use the PayZephyr::extend() method to customize provider behavior:
    PayZephyr::extend('paystack', function ($payzephyr, $provider) {
        $provider->setCustomOption('metadata', ['custom_key' => 'custom_value']);
    });
    
  • Dynamic Provider Selection: Switch providers at runtime based on business logic (e.g., country-specific routing):
    $provider = request()->input('country') === 'US' ? 'stripe' : 'paystack';
    PayZephyr::setProvider($provider);
    

4. Transaction Logging

  • Audit Trail: All transactions (payments, subscriptions, refunds) are logged to the payzephyr_transactions table. Query logs for debugging:
    $logs = \KenDeNigerian\PayZephyr\Models\TransactionLog::where('transaction_id', $paymentId)->get();
    
  • Custom Logging: Extend the TransactionLog model or use observers to add custom fields to logs.

Integration Tips

Laravel Ecosystem

  • Queue Jobs: Offload payment processing to queues for better performance:
    PayZephyr::dispatchCharge($amount, $currency, $metadata)->onQueue('payments');
    
  • Nova/Panel Integration: Display payment statuses in admin panels by querying TransactionLog or creating custom resources.
  • Testing: Use the PayZephyrTestCase trait for seamless testing:
    use KenDeNigerian\PayZephyr\Testing\PayZephyrTestCase;
    
    class PaymentTest extends PayZephyrTestCase
    {
        public function test_payment_flow()
        {
            $this->mockPaystack()->shouldReceive('charge')->once();
            // Test logic here
        }
    }
    

Frontend Integration

  • Payment Links: Generate pre-filled payment links for embedded forms:
    $paymentLink = PayZephyr::createPaymentLink(1000, 'USD', [
        'email' => 'user@example.com',
        'return_url' => route('payment.success'),
    ]);
    
  • Client-Side SDKs: Use provider-specific SDKs (e.g., Paystack's paystack.js) alongside PayZephyr for seamless UX. Pass the reference or payment_id from PayZephyr to the SDK.

Advanced Use Cases

  • Multi-Currency Support: Dynamically switch currencies based on user location or product type:
    $currency = session()->get('user_currency', 'USD');
    PayZephyr::charge($amount, $currency, $metadata);
    
  • Dynamic Pricing: Fetch real-time prices from an external service and pass them to PayZephyr:
    $price = $this->priceService->getDynamicPrice($productId);
    PayZephyr::charge($price, 'USD', $metadata);
    
  • Recurring Billing: Combine subscriptions with coupons or trial periods:
    $subscription = PayZephyr::createSubscription('premium', 4999, 'USD', [
        'trial_days' => 3,
        'coupon' => 'WELCOME10',
    ]);
    

Gotchas and Tips

Pitfalls

  1. Webhook Delays:

    • Providers like Paystack or Stripe may delay webhook deliveries. Implement retry logic in your handleWebhook method or use Laravel's retry middleware.
    • Fix: Log undelivered webhooks and manually trigger reconciliation jobs:
      $undelivered = \KenDeNigerian\PayZephyr\Models\WebhookLog::where('status', 'failed')->get();
      foreach ($undelivered as $log) {
          PayZephyr::retryWebhook($log->id);
      }
      
  2. Idempotency Keys:

    • PayZephyr supports idempotency, but ensure your frontend generates unique keys for each payment attempt to avoid duplicate charges.
    • Fix: Use Laravel's Str::uuid() or a combination of user_id + timestamp:
      $idempotencyKey = Str::uuid();
      PayZephyr::charge($amount, $currency, $metadata, $idempotencyKey);
      
  3. Currency and Amount Mismatches:

    • Always ensure amounts are passed as integers (e.g., 1000 for $10.00) and currencies are valid ISO codes. Providers like Paystack reject invalid formats.
    • Fix: Validate inputs before passing to PayZephyr:
      $amount = (int) ($price * 100); // Convert to cents
      $currency = strtoupper($currency); // Ensure uppercase
      
  4. Webhook Signature Validation:

    • If testing locally, disable signature validation temporarily in config/payzephyr.php:
      'webhooks' => [
          'validate_signature' => env('APP_ENV') !== 'local',
      ],
      
    • Security Note: Re-enable validation in production.
  5. **Provider-Specific Qu

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.
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
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope