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

Recurly Client Laravel Package

recurly/recurly-client

Official PHP client for Recurly’s V3 API. Install via Composer, create a Client with your API key (US or EU region), and access all API operations in one place. Supports optional PSR-3 logging.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require recurly/recurly-client

Add to composer.json under require:

"recurly/recurly-client": "^4"
  1. Initialize Client: Store your API key securely (e.g., Laravel .env):

    RECURLY_API_KEY=your_api_key_here
    

    Initialize in a service provider or controller:

    use Recurly\Client;
    
    $client = new Client(config('recurly.api_key'));
    
  2. First Use Case: Fetch a subscription by ID:

    $subscription = $client->getSubscription('sub_123');
    return $subscription->getPlan()->getName();
    

Implementation Patterns

Core Workflows

Subscription Management

  • Create Subscription:

    $subscription = $client->createSubscription([
        'account' => ['first_name' => 'John', 'email' => 'john@example.com'],
        'plan_code' => 'premium-monthly',
        'currency' => 'USD',
        'billing_info' => ['first_name' => 'John', 'last_name' => 'Doe', 'email' => 'john@example.com']
    ]);
    
  • Update Subscription:

    $client->updateSubscription('sub_123', ['plan_code' => 'premium-annual']);
    
  • Cancel Subscription:

    $client->cancelSubscription('sub_123', ['reason' => 'customer_request']);
    

Account Operations

  • List Accounts with Pagination:

    $accounts = $client->listAccounts(['limit' => 100, 'email' => 'user@example.com']);
    foreach ($accounts as $account) {
        // Process each account
    }
    
  • Count Past Due Invoices:

    $pastDueAccounts = $client->listAccounts(['past_due' => true]);
    $count = $pastDueAccounts->getCount();
    

Invoice Handling

  • Generate Invoice:

    $invoice = $client->createInvoice('sub_123');
    
  • Collect Payment:

    $client->collectPayment('inv_456');
    

Webhooks (Laravel Integration)

Use Laravel's queue:listen to process Recurly webhooks:

// routes/web.php
Route::post('/recurly/webhook', [RecurlyWebhookHandler::class, 'handle']);

// app/Services/RecurlyWebhookHandler.php
use Recurly\Client;
use Illuminate\Support\Facades\Log;

class RecurlyWebhookHandler {
    public function handle(Request $request) {
        $client = new Client(config('recurly.api_key'));
        $event = $client->verifyWebhook($request->getContent());

        // Process event (e.g., subscription canceled)
        if ($event->getType() === 'subscription_canceled') {
            Log::info("Subscription canceled: {$event->getSubscription()->getId()}");
        }
    }
}

Integration Tips

  1. Laravel Service Provider: Bind the client to the container for dependency injection:

    // app/Providers/AppServiceProvider.php
    public function register() {
        $this->app->singleton(Client::class, function ($app) {
            return new Client(config('recurly.api_key'));
        });
    }
    
  2. API Rate Limiting: Use the getRateLimitRemaining() method to handle rate limits gracefully:

    $response = $client->getSubscription('sub_123')->getResponse();
    if ($response->getRateLimitRemaining() < 5) {
        sleep(1); // Throttle requests
    }
    
  3. Error Handling Middleware: Create a middleware to catch Recurly errors globally:

    // app/Http/Middleware/HandleRecurlyErrors.php
    public function handle($request, Closure $next) {
        try {
            return $next($request);
        } catch (\Recurly\RecurlyError $e) {
            Log::error("Recurly Error: " . $e->getMessage());
            return response()->json(['error' => 'Recurly API error'], 500);
        }
    }
    
  4. Testing: Use Laravel's Mockery to mock the client in tests:

    $mockClient = Mockery::mock(Client::class);
    $mockClient->shouldReceive('getSubscription')
               ->with('sub_123')
               ->andReturn(new \Recurly\Subscription(['state' => 'active']));
    

Gotchas and Tips

Pitfalls

  1. API Key Exposure:

    • Never log the API key or commit it to version control.
    • Use Laravel's .env and config('recurly.api_key') for secure access.
  2. Pagination Lazy Loading:

    • list* methods return a Pager that does not make API calls until iterated.
    • Avoid calling getCount() or getFirst() in loops; it triggers API calls per invocation.
  3. Time Zone Handling:

    • Recurly uses UTC for all timestamps. Convert to local time in your application:
      $createdAt = $subscription->getCreatedAt()->format('Y-m-d H:i:s');
      
  4. Webhook Verification:

    • Always verify webhook signatures using verifyWebhook() to prevent spoofing:
      $event = $client->verifyWebhook($request->getContent(), $request->header('X-Recurly-Signature'));
      
  5. Idempotency:

    • Use idempotency_key for create* operations to avoid duplicate charges:
      $client->createSubscription($data, ['idempotency_key' => 'unique_key_123']);
      

Debugging Tips

  1. Enable Logging:

    • Set log level to DEBUG in development (but never in production):
      $logger = new \Recurly\Logger('Recurly', \Psr\Log\LogLevel::DEBUG);
      $client = new Client(config('recurly.api_key'), $logger);
      
  2. Inspect HTTP Metadata:

    • Use getResponse() to debug API calls:
      $response = $client->getSubscription('sub_123')->getResponse();
      Log::debug("Request ID: " . $response->getRequestId());
      Log::debug("Response Body: " . $response->getBodyAsJson());
      
  3. Common Errors:

    • Validation: Check err.params for invalid fields.
    • NotFound: Verify IDs (e.g., subscription/account IDs).
    • RateLimit: Implement exponential backoff for retries.

Extension Points

  1. Custom Resources:

    • Extend \Recurly\Resource to add domain-specific methods:
      class CustomSubscription extends \Recurly\Subscription {
          public function isPremium() {
              return $this->getPlan()->getCode() === 'premium';
          }
      }
      
  2. Middleware for API Calls:

    • Wrap the client to add pre/post-processing:
      class RecurlyClientDecorator {
          protected $client;
      
          public function __construct(Client $client) {
              $this->client = $client;
          }
      
          public function getSubscription($id) {
              $subscription = $this->client->getSubscription($id);
              // Add custom logic (e.g., cache results)
              return $subscription;
          }
      }
      
  3. Event Dispatching:

    • Trigger Laravel events for Recurly webhooks:
      event(new SubscriptionCanceled($event->getSubscription()));
      
  4. Testing Utilities:

    • Create a trait for testing Recurly interactions:
      trait RecurlyTestTrait {
          protected function mockRecurlyClient() {
              $mock = Mockery::mock(Client::class);
              // Setup mock responses...
              return $mock;
          }
      }
      
  5. EU Region Support:

    • Always specify the region (eu or us) when initializing the client:
      $client = new Client(config('recurly.api_key'), ['region' => 'eu']);
      

---
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