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

Salesforce Outbound Message Bundle Laravel Package

comsave/salesforce-outbound-message-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Dependencies

    composer require comsave/salesforce-outbound-message-bundle comsave/salesforce-mapper-bundle doctrine/mongodb-odm
    

    Ensure MongoDB is configured in your config/packages/doctrine_mongodb_odm.yaml.

  2. Register the Bundle Add to config/bundles.php:

    Comsave\SalesforceOutboundMessageBundle\ComsaveSalesforceOutboundMessageBundle::class => ['all' => true],
    
  3. Configure Salesforce Mapping Use comsave/salesforce-mapper-bundle to define how Salesforce objects map to your MongoDB Document classes. Example:

    # config/packages/comsave_salesforce_mapper.yaml
    comsave_salesforce_mapper:
        mappings:
            Lead:
                class: App\Entity\Lead
                fields:
                    - id
                    - first_name
                    - last_name
    
  4. First Use Case: Handling an Outbound Message Configure a listener to process incoming Salesforce outbound messages. Example in config/packages/comsave_salesforce_outbound_message.yaml:

    comsave_salesforce_outbound_message:
        listeners:
            Lead:
                class: App\EventListener\SalesforceLeadListener
                method: onLeadUpdate
    

Implementation Patterns

Core Workflow

  1. Define Listeners Create event listeners for specific Salesforce objects (e.g., Lead, Account). Example:

    // src/EventListener/SalesforceLeadListener.php
    namespace App\EventListener;
    
    use Comsave\SalesforceOutboundMessageBundle\Event\SalesforceOutboundMessageEvent;
    use App\Entity\Lead;
    
    class SalesforceLeadListener
    {
        public function onLeadUpdate(SalesforceOutboundMessageEvent $event)
        {
            $data = $event->getData();
            $lead = new Lead();
            $lead->hydrate($data); // Assuming hydrate() is defined in your Document
            $event->getDocumentManager()->persist($lead);
        }
    }
    
  2. Leverage beforeFlush and afterFlush Customize behavior before/after processing:

    # config/packages/comsave_salesforce_outbound_message.yaml
    comsave_salesforce_outbound_message:
        listeners:
            Lead:
                class: App\EventListener\SalesforceLeadListener
                method: onLeadUpdate
                before_flush: true  # Optional: Run logic before persisting
                after_flush: true   # Optional: Run logic after persisting
    
  3. Handle Deletes Enable deletion support by following README-setup-removal.md. Example listener:

    public function onLeadDelete(SalesforceOutboundMessageEvent $event)
    {
        $id = $event->getData()['Id'];
        $lead = $event->getDocumentManager()->find(Lead::class, $id);
        if ($lead) {
            $event->getDocumentManager()->remove($lead);
        }
    }
    
  4. Batch Processing For high-volume messages, implement batch processing in your listener:

    public function onBulkLeadUpdate(SalesforceOutboundMessageEvent $event)
    {
        $dm = $event->getDocumentManager();
        $batch = $event->getData();
        foreach ($batch as $leadData) {
            $lead = new Lead();
            $lead->hydrate($leadData);
            $dm->persist($lead);
        }
        $dm->flush();
    }
    
  5. Integration with Symfony Messenger Offload processing to a queue for async handling:

    # config/packages/messenger.yaml
    framework:
        messenger:
            transports:
                salesforce: '%env(MESSENGER_TRANSPORT_DSN)%'
            routing:
                'Comsave\SalesforceOutboundMessageBundle\Message\SalesforceOutboundMessage': salesforce
    

Gotchas and Tips

Common Pitfalls

  1. MongoDB ID Mismatch

    • Ensure Salesforce Id fields map to MongoDB _id or a custom field. Example:
      // In your Document class
      /**
       * @MongoDB\Id(strategy="UUID")
       * @MongoDB\Field(type="string")
       */
      private $salesforceId;
      
    • Fix: Use comsave/salesforce-mapper-bundle to explicitly map Salesforce IDs.
  2. Circular References

    • Salesforce outbound messages may include nested objects (e.g., Contact under Account). MongoDB ODM may fail with circular references.
    • Fix: Use @MongoDB\ReferenceOne or @MongoDB\EmbedOne annotations carefully, or flatten nested data in your listener.
  3. Duplicate Processing

    • Outbound messages may trigger duplicate create/update calls if not handled idempotently.
    • Fix: Add a unique index on Salesforce Id in your MongoDB collection or implement a deduplication check in your listener:
      if (!$dm->getRepository(Lead::class)->findOneBy(['salesforceId' => $data['Id']])) {
          $dm->persist($lead);
      }
      
  4. Listener Ordering

    • If multiple listeners handle the same object, ensure correct execution order by configuring priorities in comsave_salesforce_outbound_message.yaml:
      listeners:
          Lead:
              class: App\EventListener\LeadPriorityListener
              method: onLeadUpdate
              priority: 100  # Higher priority runs first
      
  5. Timezone Issues

    • Salesforce timestamps may not align with your app’s timezone, causing beforeFlush/afterFlush logic to fail.
    • Fix: Normalize timestamps in your listener:
      $data['CreatedDate'] = (new \DateTime($data['CreatedDate']))->setTimezone(new \DateTimeZone('UTC'));
      

Debugging Tips

  1. Enable Verbose Logging Configure Monolog to log outbound message events:

    # config/packages/monolog.yaml
    monolog:
        handlers:
            salesforce:
                type: stream
                path: "%kernel.logs_dir%/salesforce_outbound.log"
                level: debug
                channels: ["salesforce"]
    

    Then log in your listener:

    $this->logger->debug('Processing Salesforce data', ['data' => $event->getData()]);
    
  2. Validate Incoming Data Use Symfony’s Validator to validate Salesforce payloads:

    use Symfony\Component\Validator\Validator\ValidatorInterface;
    
    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;
    }
    
    public function onLeadUpdate(SalesforceOutboundMessageEvent $event)
    {
        $errors = $this->validator->validate($event->getData());
        if (count($errors) > 0) {
            throw new \RuntimeException('Invalid Salesforce data: ' . (string) $errors);
        }
        // Process data...
    }
    
  3. Test with Mock Data Unit test listeners with mock SalesforceOutboundMessageEvent:

    use Comsave\SalesforceOutboundMessageBundle\Event\SalesforceOutboundMessageEvent;
    use Doctrine\ODM\MongoDB\DocumentManager;
    
    $dm = $this->createMock(DocumentManager::class);
    $event = new SalesforceOutboundMessageEvent($dm, ['Id' => '001xxxx', 'Name' => 'Test Lead']);
    $listener = new SalesforceLeadListener();
    $listener->onLeadUpdate($event);
    

Extension Points

  1. Custom Event Subscribers Extend the bundle’s event system by creating custom subscribers:

    use Comsave\SalesforceOutboundMessageBundle\Event\SalesforceOutboundMessageEvents;
    
    class CustomSalesforceSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                SalesforceOutboundMessageEvents::PRE_PROCESS => 'onPreProcess',
            ];
        }
    
        public function onPreProcess(SalesforceOutboundMessageEvent $event)
        {
            // Pre-process logic (e.g., enrich data)
        }
    }
    
  2. Dynamic Mapping Override default mappings at runtime:

    $event->setMapper(new CustomSalesforceMapper($event->getData()));
    
  3. Webhook Validation Validate Salesforce webhook signatures if using HTTPS endpoints:

    use Comsave\SalesforceOutboundMessageBundle\Security\SalesforceSignatureValidator;
    
    $validator = new SalesforceSignatureValidator('your_webhook_secret');
    if (!$validator->isValid($request)) {
        throw new \RuntimeException('Invalid Salesforce webhook signature');
    }
    
  4. Async Processing with Doctrine Events Use Doctrine lifecycle events for async operations:

    $
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui