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

Pwinty Bundle Laravel Package

buendon/pwinty-bundle

Symfony bundle providing a service and OO API to interact with the Pwinty photo printing API (via php-pwinty fork). Configure merchant ID, API key, and sandbox/production endpoints, then create and submit orders from your Symfony app.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   - Add the custom repository and dependencies to `composer.json`:
     ```json
     "repositories": [{
         "type": "vcs",
         "url": "https://github.com/Buendon/php-pwinty"
     }],
     "require": {
         "pwinty/php-pwinty": "dev-api_2.3",
         "buendon/pwinty-bundle": "dev-master"
     }
     ```
   - Run `composer update buendon/pwinty-bundle pwinty/php-pwinty`.
   - Register the bundle in `config/bundles.php`:
     ```php
     return [
         // ...
         Buendon\PwintyBundle\BuendonPwintyBundle::class => ['all' => true],
     ];
     ```

2. **Configuration**:
   - Add Pwinty config to `config/packages/buendon_pwinty.yaml`:
     ```yaml
     buendon_pwinty:
         apiType: 'sandbox'  # or 'production'
         merchantId: '%env(PWINTY_MERCHANT_ID)%'
         apiKey: '%env(PWINTY_API_KEY)%'
     ```
   - Store credentials in `.env`:
     ```
     PWINTY_MERCHANT_ID=your_merchant_id
     PWINTY_API_KEY=your_api_key
     ```

3. **First Use Case**:
   - Inject `PwintyService` into a controller/service and create an order:
     ```php
     use Buendon\PwintyBundle\Service\PwintyService;
     use Buendon\PwintyBundle\Order\Order;

     public function createOrder(PwintyService $pwintyService) {
         $order = new Order();
         $order->setRecipientName("John Doe")
               ->setAddress1("123 Main St")
               ->setCountryCode("FR")
               ->setPayment(Order::PAYMENT_INVOICE_ME);

         $response = $pwintyService->createOrder($order);
         return $response->getId();
     }
     ```

---

## Implementation Patterns

### Core Workflows
1. **Order Management**:
   - **Create**: Use `PwintyService::createOrder(Order $order)`.
   - **Update**: Modify order properties (e.g., `setRecipientName()`) and call `updateOrder($orderId, $order)`.
   - **Submit**: Transition to `Order::UPDATE_STATUS_SUBMITTED` via `updateOrderStatus($orderId, $status)`.

2. **Photo Handling**:
   - Add photos to an order with `addPhoto($orderId, Photo $photo)`.
   - Configure `Photo` with type (e.g., `'9x12_cm'`), sizing (`SIZING_CROP`), and file path.

3. **Status Checks**:
   - Fetch order details with `getOrder($orderId)`.
   - Check submission status with `getOrderSubmissionStatus($orderId)`.

4. **Error Handling**:
   - Wrap API calls in `try-catch` blocks for `OrderException`.
   - Log exceptions for debugging:
     ```php
     catch (OrderException $e) {
         $this->logger->error('Pwinty API Error', ['error' => $e->getMessage()]);
     }
     ```

### Integration Tips
- **Dependency Injection**:
  - Prefer constructor injection for `PwintyService` in services/controllers.
  - Example:
    ```php
    public function __construct(private PwintyService $pwintyService) {}
    ```

- **Environment Awareness**:
  - Use `sandbox` mode for development/testing to avoid real charges.
  - Switch to `production` in staging/production via config.

- **Batch Processing**:
  - For bulk orders, loop through entities and submit in batches to avoid API rate limits:
    ```php
    foreach ($orders as $order) {
        $pwintyService->createOrder($order);
        sleep(1); // Respect API rate limits
    }
    ```

- **Event-Driven Workflows**:
  - Listen for order submission completion via webhooks (Pwinty API) and trigger Symfony events:
    ```php
    // In a webhook handler
    $event = new OrderSubmittedEvent($orderId);
    $this->eventDispatcher->dispatch($event, OrderEvents::ORDER_SUBMITTED);
    ```

---

## Gotchas and Tips

### Pitfalls
1. **API Version Mismatch**:
   - The bundle relies on a fork (`php-pwinty`) of the original Pwinty SDK. Ensure the fork is updated to match Pwinty API v2.3.
   - **Fix**: Monitor the [php-pwinty repo](https://github.com/Buendon/php-pwinty) for updates or submit PRs to the fork.

2. **File Uploads**:
   - Photos must be local files (not URLs). Use temporary files for uploaded content:
     ```php
     $tempFile = tempnam(sys_get_temp_dir(), 'pwinty_');
     file_put_contents($tempFile, $photoData);
     $photo->setFile($tempFile);
     // Clean up after submission
     unlink($tempFile);
     ```

3. **Sandbox vs. Production**:
   - Forgetting to switch `apiType` to `production` will cause orders to fail silently or be rejected.
   - **Tip**: Use a feature flag or environment variable to toggle modes dynamically.

4. **Rate Limiting**:
   - Pwinty API has strict rate limits (e.g., 10 requests/minute). Exceeding limits returns `429 Too Many Requests`.
   - **Fix**: Implement exponential backoff in retries:
     ```php
     $attempts = 0;
     while ($attempts < 3) {
         try {
             $response = $pwintyService->createOrder($order);
             break;
         } catch (OrderException $e) {
             if ($e->getCode() === 429) {
                 sleep(2 ** $attempts); // Exponential backoff
                 $attempts++;
             } else {
                 throw $e;
             }
         }
     }
     ```

5. **Order Validation**:
   - Pwinty validates orders strictly (e.g., missing `countryCode` or invalid `payment` type).
   - **Tip**: Validate locally before submission:
     ```php
     if (!$order->getCountryCode() || !in_array($order->getPayment(), [Order::PAYMENT_INVOICE_ME, Order::PAYMENT_PREPAID])) {
         throw new \InvalidArgumentException('Invalid order data');
     }
     ```

### Debugging Tips
- **Enable API Debugging**:
  - Set `PWINTY_DEBUG=true` in `.env` to log raw API responses:
    ```yaml
    # config/packages/buendon_pwinty.yaml
    buendon_pwinty:
        debug: '%env(bool:PWINTY_DEBUG)%'
    ```

- **Common Errors**:
  - **`401 Unauthorized`**: Invalid `merchantId` or `apiKey`. Double-check `.env`.
  - **`400 Bad Request`**: Missing required fields (e.g., `recipientName`). Use `var_dump($order)` to verify.
  - **`500 Internal Server Error`**: Pwinty API issue. Check [Pwinty Status](http://status.pwinty.com).

### Extension Points
1. **Custom Order Mappers**:
   - Extend `Order` or `Photo` to add domain-specific fields:
     ```php
     class CustomOrder extends Order {
         public function setCustomField(string $value) {
             $this->customData['custom_field'] = $value;
         }
     }
     ```

2. **Event Listeners**:
   - Subscribe to `OrderEvents` to react to order lifecycle changes:
     ```php
     // src/EventListener/PwintyListener.php
     public static function getSubscribedEvents(): array {
         return [
             OrderEvents::ORDER_SUBMITTED => 'onOrderSubmitted',
         ];
     }
     ```

3. **API Response Transformers**:
   - Override response handling in a custom service:
     ```php
     class CustomPwintyService extends PwintyService {
         protected function transformResponse($response) {
             // Add custom logic (e.g., currency conversion)
             return parent::transformResponse($response);
         }
     }
     ```
     Register it as a service alias in `services.yaml`:
     ```yaml
     Buendon\PwintyBundle\Service\PwintyService: '@custom_pwinty_service'
     ```

4. **Testing**:
   - Mock `PwintyService` in PHPUnit:
     ```php
     $mockService = $this->createMock(PwintyService::class);
     $mockService->method('createOrder')
         ->willReturn(new OrderResponse('12345'));
     $this->container->set(PwintyService::NAME, $mockService);
     ```

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.
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
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle