public function execute(Request $request, Response $response)
 {
     parent::execute($request, $response);
     Logger::info("Starting processing of listener request from {$this->request->getClientIp()}");
     try {
         $this->doIngressSecurity();
         $soapData = $request->getRawRequest();
         $tl = Logger::getTaggedLogger('RawData');
         $tl->info($soapData);
         $response->sendHeaders();
         /* --- Unfortunately because of how PHP handles SOAP requests we cannot do the fully wrapped
         					loop like we could in the REST listener. Instead it is up to the listener itself to
         					do the required call to $this->processMessage( $msg ).
         
         					It is also expected that inside the handle() context that an exception will throw a SOAP
         					fault through $this->server->fault() instead of doing a $response->kill_response() call.
         			*/
         $this->server->setObject($this);
         $this->server->handle($soapData);
         /* We disable output late in the game in case there was a last minute exception that could
         			be handled by the SOAP listener object inside the handle() context. */
         $response->setOutputDisabled();
     } catch (ListenerSecurityException $ex) {
         Logger::notice('Message denied by security policy, death is me.', null, $ex);
         $response->setStatusCode(403, "Not authorized.");
     } catch (\Exception $ex) {
         Logger::error('Listener threw an unknown exception, death is me.', null, $ex);
         $response->setStatusCode(500, "Unknown listener exception.");
     }
     Logger::info('Finished processing listener request');
 }
 /**
  * Instantiates and runs a job defined by a queue message. Depends on
  * the base consumer's damaged message store functionality to either
  * divert messages or stop execution on bad message or job failure.
  * @param array $jobMessage
  * @throws \SmashPig\Core\DataStores\DataSerializationException
  */
 function processMessage($jobMessage)
 {
     if (!isset($jobMessage['php-message-class'])) {
         throw new RuntimeException('Job message missing required key \'php-message-class\'');
     }
     // TODO: encapsulate the reconstitution step elsewhere.
     // FIXME It seems bad that these objects indiscriminately store
     // things as properties. The message is mingled with stuff like
     // php-message-class. Could collide.
     $className = $jobMessage['php-message-class'];
     Logger::info("Hydrating a message with class {$className}");
     $jsonMessage = json_encode($jobMessage);
     Logger::debug("Job payload: {$jsonMessage}");
     $jobObj = KeyedOpaqueStorableObject::fromJsonProxy($className, $jsonMessage);
     if ($jobObj instanceof Runnable) {
         Logger::info('Running job');
         if (!$jobObj->execute()) {
             throw new RuntimeException('Job tells us that it did not successfully execute. ' . 'Sending to damaged message store.');
         }
     } else {
         // We don't know how to run this job type.
         throw new RuntimeException(get_class($jobObj) . ' is not an instance of Runnable. ' . 'Could not execute and sending to damaged message store.');
     }
     $this->successCount += 1;
 }
 public function execute(Request $request, Response $response)
 {
     parent::execute($request, $response);
     Logger::info("Starting processing of listener request from {$this->request->getClientIp()}");
     try {
         $this->doIngressSecurity();
         $msgs = $this->parseEnvelope($request);
         if (is_array($msgs)) {
             foreach ($msgs as $msg) {
                 $this->processMessage($msg);
             }
         }
         $this->ackEnvelope();
     } catch (ListenerSecurityException $ex) {
         Logger::notice('Message denied by security policy, death is me.', null, $ex);
         $response->setStatusCode(403, "Not authorized.");
     } catch (ListenerDataException $ex) {
         Logger::error('Listener received request it could not process, death is me.', null, $ex);
         $response->setStatusCode(500, 'Received data could not be processed.');
     } catch (Core\ConfigurationException $ex) {
         Logger::alert('Some sad panda gave me a bad configuration.', null, $ex);
         $response->setStatusCode(500, "Configuration error.");
     } catch (\Exception $ex) {
         Logger::error('Listener threw an unknown exception, death is me.', null, $ex);
         $response->setStatusCode(500, "Unknown listener exception");
     }
     Logger::info('Finished processing listener request');
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     $this->datastore = BaseQueueConsumer::getQueue($this->getOption('queue'));
     $startTime = time();
     $messageCount = 0;
     // Open the file for read
     $infile = $this->getArgument('file');
     $f = fopen($infile, 'r');
     if (!$f) {
         $this->error("Could not open {$infile} for read", true);
     }
     // Do the loop!
     while (($line = fgets($f)) !== false) {
         if (substr($line, 0, 4) === 'raw=') {
             $message = $this->decodeLegacyMessage($line);
         } else {
             $message = json_decode($line, true);
         }
         if ($message === null) {
             Logger::error("Invalid line: {$line}");
             continue;
         }
         $this->datastore->push($message);
         $messageCount++;
         if ($messageCount % 1000 == 0) {
             print '.';
         }
     }
     print '\\n';
     $elapsedTime = time() - $startTime;
     Logger::info("Imported {$messageCount} messages from {$infile} in {$elapsedTime} seconds.");
 }
 protected function parseEnvelope(Request $request)
 {
     $requestValues = $request->getValues();
     $secureLog = Logger::getTaggedLogger('RawData');
     $secureLog->info("Incoming message (raw)", $requestValues);
     $messages = array();
     // Can't even check signature without these four
     $required = array('result', 'x_amount', 'x_invoice', 'x_control');
     $missing = array_diff($required, array_keys($requestValues));
     if (count($missing)) {
         $list = implode(',', $missing);
         throw new ListenerDataException("AstroPay message missing required key(s) {$list}.");
     }
     $result = $requestValues['result'];
     if (array_key_exists($result, $this->byResult)) {
         $klass = $this->byResult[$result];
         $message = new $klass();
         $message->constructFromValues($requestValues);
         $secureLog->debug("Found message ", $message);
         $messages[] = $message;
     } else {
         Logger::info("Message ignored: result = {$result}");
     }
     return $messages;
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     $basePath = 'maintenance/consume-pending/';
     $consumer = new PendingQueueConsumer($this->getOption('queue'), $this->getOptionOrConfig('time-limit', $basePath . 'time-limit'), $this->getOptionOrConfig('max-messages', $basePath . 'message-limit'));
     $startTime = time();
     $messageCount = $consumer->dequeueMessages();
     $elapsedTime = time() - $startTime;
     Logger::info("Processed {$messageCount} pending messages in {$elapsedTime} seconds.");
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     // The logger will print out to the console; and any other log streams that have
     // been configured.
     Logger::info($this->getOption('message'));
     // Other fun functions to know about:
     // - readConsole() - get input from the console
     // - error() - error out and die with a message
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     // Get some defaults from configuration
     $basePath = 'maintenance/job-runner/';
     $consumer = new JobQueueConsumer($this->getOption('queue'), $this->getOptionOrConfig('time-limit', $basePath . 'time-limit'), $this->getOptionOrConfig('max-messages', $basePath . 'message-limit'));
     $startTime = time();
     $messageCount = $consumer->dequeueMessages();
     $successCount = $consumer->getSuccessCount();
     $elapsedTime = time() - $startTime;
     Logger::info("Processed {$messageCount} ({$successCount} successful) jobs in {$elapsedTime} seconds.");
 }
 public function processMessage($message)
 {
     $logIdentifier = "message with gateway {$message['gateway']}" . " and order ID {$message['order_id']}";
     if ($this->paymentsInitialDatabase->isTransactionFailed($message)) {
         // Throw the message out if it's already failed
         Logger::info("Skipping failed {$logIdentifier}");
     } else {
         Logger::info("Storing {$logIdentifier} in database");
         $this->pendingDatabase->storeMessage($message);
     }
 }
 /**
  * Renames the current logging context. Effects the log prefix used for all
  * events under this context. May have adverse effects on logstreams that log
  * in real time (IE: Syslog) because they will have logged items under the old
  * context name.
  *
  * @param string   $newName     New name for the current context
  * @param bool     $addLogEntry If false will not create a log line stating the name change
  *
  * @return string The old name of this context
  */
 public function renameContext($newName, $addLogEntry = true)
 {
     $old = $this->contextNames[0];
     if ($addLogEntry) {
         Logger::info("Renaming logging context '{$old}' to '{$newName}'.");
     }
     $this->contextNames[0] = $newName;
     foreach ($this->logStreams as $stream) {
         $stream->renameContext($this->contextNames, $old);
     }
     return $old;
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     Logger::info('Info log message');
     Logger::debug('Debug log message');
     Logger::notice('Notice...');
     Logger::getTaggedLogger('RawData')->info('This should be tagged RawData');
     Logger::warning('Warning!', array('foo' => 'bar'));
     try {
         $this->throwException();
     } catch (SmashPigException $ex) {
         Logger::error('ERROR!!!!', null, $ex);
     }
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     $this->datastore = new StompDataStore($this->getOption('queue'));
     $maxMessages = $this->getOption('max-messages');
     $startTime = time();
     $messageCount = 0;
     $raw = $this->getOption('raw');
     $ignore = $this->getOption('no-ack');
     // Construct the selectors
     $argId = 0;
     $selectors = array();
     while ($this->hasArgument($argId)) {
         $selectors[] = $this->getArgument($argId);
         $argId += 1;
     }
     // Open the file for write-append
     $outfile = $this->getOption('outfile');
     $f = fopen($outfile, 'a');
     if (!$f) {
         $this->error("Could not open {$outfile} for write append", true);
     }
     // Do the loop!
     do {
         // This is actually quite inefficient; but this whole thing is a hack so meh!
         // ...Ideally we would take the JSON from the store directly instead of walking
         // it through an object
         try {
             $queueObj = $this->datastore->queueGetObject(null, null, $selectors, !$raw);
             if (!$queueObj) {
                 break;
             }
             if ($raw) {
                 fwrite($f, 'raw' . "=" . json_encode($queueObj) . "\n");
             } else {
                 fwrite($f, get_class($queueObj) . "=" . $queueObj->toJson(false) . "\n");
             }
         } catch (DataSerializationException $ex) {
             // We probably caught an anti-message here; log the exception and continue on
             Logger::warning("Possibly caught an antimessage. Not adding to file.", null, $ex);
         }
         if ($ignore) {
             $this->datastore->queueIgnoreObject();
         } else {
             $this->datastore->queueAckObject();
         }
         $messageCount += 1;
     } while ($maxMessages === 0 || $messageCount < $maxMessages);
     $elapsedTime = time() - $startTime;
     Logger::info("Dumped {$messageCount} messages to {$outfile} in {$elapsedTime} seconds.");
 }
 /**
  * Will run all the actions that are loaded (from the 'actions' configuration
  * node) and that are applicable to this message type. Will return true
  * if all actions returned true. Otherwise will return false. This implicitly
  * means that the message will be re-queued if any action fails. Therefore
  * all actions need to be idempotent.
  *
  * @returns bool True if all actions were successful. False otherwise.
  */
 public function runActionChain()
 {
     Logger::info("Received new report from Adyen: {$this->pspReference}. Generated: {$this->eventDate}.", $this->reason);
     $jobQueue = BaseQueueConsumer::getQueue('jobs-adyen');
     if (strpos($this->pspReference, 'settlement_detail_report') === 0) {
         $jobObject = DownloadReportJob::factory($this->merchantAccountCode, $this->reason);
         // FIXME: write queue wrapper to do these next two steps
         SourceFields::addToMessage($jobObject);
         $jobArray = json_decode($jobObject->toJson(), true);
         $jobQueue->push($jobArray);
     } else {
         // We don't know how to handle this report yet
         Logger::notice("Do not know how to handle report with name '{$this->pspReference}'");
     }
     return parent::runActionChain();
 }
 protected function downloadReport($reportInfo)
 {
     $id = $reportInfo['ReportId'];
     // Remove common prefix from report type
     $type = str_replace('_GET_FLAT_FILE_OFFAMAZONPAYMENTS_', '', $reportInfo['ReportType']);
     if (array_search($id, $this->downloadedIds) === false) {
         Logger::debug("Downloading report dated {$reportInfo['AvailableDate']} with id: {$id}");
         $report = $this->reportsClient->getReport(array('report_id' => $id));
         $date = substr($reportInfo['AvailableDate'], 0, 10);
         $path = "{$this->downloadPath}/{$date}-{$type}{$id}.csv";
         Logger::info("Saving report to {$path}");
         file_put_contents($path, $report['ResponseBody']);
     } else {
         Logger::debug("Skipping downloaded report with id: {$id}");
     }
 }
 public function execute(ListenerMessage $msg)
 {
     // Bail out if not a refund
     if (get_class($msg) !== self::MESSAGE_CLASS) {
         return true;
     }
     $refundId = $msg->getGatewayTransactionId();
     Logger::info("Looking up ID of original transaction for refund {$refundId}");
     try {
         $parentId = AmazonApi::findRefundParentId($refundId);
         $msg->setParentId($parentId);
         return true;
     } catch (SmashPigException $ex) {
         Logger::error($ex->getMessage());
         return false;
     }
 }
 protected function parseEnvelope(Request $request)
 {
     // Symfony's framework gives us each header's value as an array
     // (to account for potential repeated headers?
     // IpnHandler's constructor expects scalar values, so we flatten them
     $headers = array();
     foreach ($request->headers->all() as $header => $annoyingArray) {
         if (count($annoyingArray) !== 1) {
             throw new ListenerDataException("header '{$header}' should have a single value");
         }
         $headers[$header] = $annoyingArray[0];
     }
     $json = $request->getRawRequest();
     $secureLog = Logger::getTaggedLogger('RawData');
     $secureLog->info('Incoming message (raw)', array('headers' => $headers, 'body' => $json));
     $messages = array();
     try {
         $amazonHandlerMessage = AmazonApi::createIpnHandler($headers, $json);
     } catch (\Exception $ex) {
         // FIXYOU: IpnHandler should use exception subclasses or error codes
         // Assuming here that IpnHandler's problem was with the signature
         // We can get away with throwing ListenerSecurityException here
         // because of how RestListener is implemented and because we only
         // process one message per request
         // Bad form, but it would be odd to hold this till doMessageSecurity
         throw new ListenerSecurityException($ex->getMessage());
     }
     $messageValues = $amazonHandlerMessage->toArray();
     $type = $messageValues['NotificationType'];
     if (array_key_exists($type, $this->messageClasses)) {
         $byStatus = $this->messageClasses[$type];
         $status = $this->getMessageStatus($messageValues, $type);
         if (array_key_exists($status, $byStatus)) {
             $klass = $byStatus[$status];
             $message = new $klass($messageValues);
             $secureLog->debug('Created message', $message);
             $messages[] = $message;
         } else {
             Logger::info("Message ignored: status = {$status}");
         }
     } else {
         Logger::info("Message ignored: notificationType = {$type}");
     }
     return $messages;
 }
 public function execute(ListenerMessage $msg)
 {
     // only close after successful capture
     if (get_class($msg) !== self::MESSAGE_CLASS) {
         return true;
     }
     $config = Context::get()->getConfiguration();
     $client = $config->object('payments-client', true);
     $captureId = $msg->getGatewayTransactionId();
     $orderReferenceId = substr($captureId, 0, 19);
     Logger::info("Closing order reference {$orderReferenceId}");
     $response = $client->closeOrderReference(array('amazon_order_reference_id' => $orderReferenceId))->toArray();
     if (!empty($response['Error'])) {
         Logger::info("Error losing order reference {$orderReferenceId}: " . $response['Error']['Code'] . ': ' . $response['Error']['Message']);
         return false;
     }
     return true;
 }
 /**
  * Determine remote IP address and check validity against an IP whitelist. Will throw exception
  * on error or invalid IP.
  *
  * TODO: This function only handles IPv4 -- it should also handle v6
  *
  * @throws ListenerConfigException
  * @throws ListenerSecurityException
  */
 protected function validateRemoteIp()
 {
     // Obtain whitelist
     $whitelist = $this->c->val('security/ip-whitelist', true);
     // Obtain remote party IP
     $remote_ip = $this->request->getClientIp();
     // Do we continue?
     if (empty($whitelist)) {
         Logger::info("No IP whitelist specified. Continuing and not validating remote IP '{$remote_ip}'.");
         return;
     }
     // Validate remote party IP (right now we can only handle IPv4)
     if (!filter_var($remote_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
         throw new ListenerSecurityException("Bizarre remote IP address: {$remote_ip}");
     }
     // Check remote address against the IP whitelist -- the whitelist can be either individual
     // or CIDR blocks.
     foreach ((array) $whitelist as $ip) {
         if ($remote_ip === $ip) {
             return;
         } elseif (count(explode('/', $ip)) === 2) {
             // Obtain address, CIDR block, and verify correctness of form
             list($network_ip, $block) = explode('/', $ip);
             if (!filter_var($network_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) || !filter_var($block, FILTER_VALIDATE_INT, array('min_range' => 0, 'max_range' => 32))) {
                 throw new ListenerConfigException("Malformed IP address in whitelist: {$ip}");
             }
             // Obtain raw IP addresses
             $network_long = ip2long($network_ip);
             $mask_long = ~(pow(2, 32 - $block) - 1);
             $remote_long = ip2long($remote_ip);
             // Validate in CIDR
             if (($remote_long & $mask_long) === ($network_long & $mask_long)) {
                 return;
                 // the remote IP address is in this range
             }
         } else {
             throw new ListenerConfigException("Malformed IP address in whitelist: {$ip}");
         }
     }
     // we have fallen through everything in the whitelist, throw
     $agent = $this->request->server->get('User-Agent', '');
     throw new ListenerSecurityException("Received a connection from a bogus IP: {$remote_ip}, agent: {$agent}");
 }
 public function __construct($path)
 {
     $this->basePath = $path;
     $this->objectsPath = $this->basePath . '/objects';
     $this->keysPath = $this->basePath . '/keys';
     Logger::debug("Constructing DiskFileStore with path {$this->basePath}");
     if (!file_exists($this->basePath) && !mkdir($this->basePath, 0770, true)) {
         Logger::info("Could not create base store directory {$this->basePath}");
         throw new DataStoreException("Could not create writeable directory: '{$this->basePath}'");
     }
     if (!file_exists($this->objectsPath) && !mkdir($this->objectsPath, 0770, true)) {
         Logger::info("Could not create object store directory {$this->objectsPath}");
         throw new DataStoreException("Could not create writeable directory: '{$this->objectsPath}'");
     }
     if (!file_exists($this->keysPath) && !mkdir($this->keysPath, 0770, true)) {
         Logger::info("Could not create key links store directory {$this->keysPath}");
         throw new DataStoreException("Could not create writeable directory: '{$this->keysPath}'");
     }
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     $pendingDatabase = PendingDatabase::get();
     $numCreated = 0;
     $limit = $this->getOptionOrConfig('max-messages', 'maintenance/create-ipns/message-limit');
     $output = $this->getOption('output-dir');
     $gateway = $this->getArgument('gateway');
     $pendingMessages = $pendingDatabase->fetchMessagesByGatewayNewest($gateway, $limit);
     if (!$pendingMessages) {
         Logger::info("No pending database entries found for {$gateway}");
         return;
     }
     $this->templateDir = __DIR__ . '/../Tests/IPNTemplates/' . $gateway . '/';
     $templates = scandir($this->templateDir);
     foreach ($pendingMessages as $pendingMessage) {
         $this->createIpnMessages($pendingMessage, $templates, $output);
         $numCreated++;
     }
     Logger::info("Created {$numCreated} (sets of) IPN messages.");
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     $this->datastore = Context::get()->getConfiguration()->object('data-store/' . $this->getArgument(0, 'test'), false);
     // Generate a whole bunch of random data
     while (count($this->testObjects) < 10) {
         $this->testObjects[] = TestObject::factory();
     }
     // And repeat the objects and inject so we have something else to find
     foreach ($this->testObjects as $obj) {
         $this->datastore->addObject($obj);
         $this->datastore->addObject(TestObject::factory($obj->correlationId));
     }
     // Mix up the order of the objects to simulate real life
     shuffle($this->testObjects);
     // Now attempt to find them and their pairs!
     $this->datastore = Context::get()->getConfiguration()->object('data-store/' . $this->getArgument(0, 'test'), false);
     foreach ($this->testObjects as $obj) {
         $obj1 = $this->datastore->queueGetObject(null, $obj->correlationId);
         if ($obj1 !== null) {
             $this->datastore->queueAckObject();
         } else {
             $this->error("Could not find original object with id {$obj->correlationId}");
             continue;
         }
         $obj2 = $this->datastore->queueGetObject(null, $obj->correlationId);
         if ($obj2 !== null) {
             $this->datastore->queueAckObject();
         } else {
             $this->error("Could not find secondary object with id {$obj->correlationId}");
             continue;
         }
         $obj3 = $this->datastore->queueGetObject(null, $obj->correlationId);
         if ($obj3 !== null) {
             $this->datastore->queueAckObject();
             $this->error("Found tertiary object with id {$obj3->correlationId} " . "while looking for id {$obj->correlationId}");
             continue;
         }
         Logger::info("Successfully found id {$obj->correlationId}");
     }
     Logger::info("Done");
 }
 public function execute(Request $request, Response $response)
 {
     $this->config = Configuration::getDefaultConfig();
     $requestValues = $request->getValues();
     // Don't store blank messages.
     if (empty($requestValues)) {
         return;
     }
     // Don't store invalid messages.
     $valid = $this->config->object('api')->validate($requestValues);
     if (!$valid) {
         // This will tell them to resend later.
         $response->setStatusCode(403, 'Failed verification');
         return false;
     }
     // Dump the request right into the queue with no validation.
     $job = new Job();
     $job->payload = $requestValues;
     $this->config->object('data-store/jobs-paypal')->push($job);
     Logger::info('Pushed new message to jobs-paypal: ' . print_r($requestValues, true));
 }
 /**
  * Will run all the actions that are loaded (from the 'actions' configuration
  * node) and that are applicable to this message type. Will return true
  * if all actions returned true. Otherwise will return false. This implicitly
  * means that the message will be re-queued if any action fails. Therefore
  * all actions need to be idempotent.
  *
  * @returns bool True if all actions were successful. False otherwise.
  */
 public function runActionChain()
 {
     $retval = true;
     // TODO: Cache this?
     $actions = Context::get()->getConfiguration()->val('actions');
     foreach ($actions as $actionClassName) {
         $action = new $actionClassName();
         if ($action instanceof IListenerMessageAction) {
             Logger::debug("Running action {$actionClassName}.");
             if (!$action->execute($this)) {
                 Logger::info("Action {$actionClassName} did not execute properly, will re-queue.");
                 $retval = false;
                 break;
             } else {
                 Logger::debug("Action returned success.");
             }
         } else {
             Logger::error("Entry under actions node '{$actionClassName}' does not implement IListenerActionMessage");
         }
     }
     return $retval;
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     $this->damagedDatabase = DamagedDatabase::get();
     $messages = $this->damagedDatabase->fetchRetryMessages($this->getOption('max-messages'));
     $stats = array();
     $config = Configuration::getDefaultConfig();
     foreach ($messages as $message) {
         $queueName = $message['original_queue'];
         // FIXME: getting it by alias, this will be annoying cos -new
         $queue = BaseQueueConsumer::getQueue($queueName);
         unset($message['original_queue']);
         $queue->push($message);
         $this->damagedDatabase->deleteMessage($message);
         if (isset($stats[$queueName])) {
             $stats[$queueName]++;
         } else {
             $stats[$queueName] = 1;
         }
     }
     foreach ($stats as $queueName => $count) {
         Logger::info("Requeued {$count} messages to {$queueName}.");
     }
 }
 /**
  * Do the actual work of the script.
  */
 public function execute()
 {
     $this->datastore = new StompDataStore($this->getOption('queue'));
     $this->damagedDatastore = new StompDataStore($this->getOption('damaged-queue'));
     $startTime = time();
     $messageCount = 0;
     $successCount = 0;
     do {
         $jobObj = $this->datastore->queueGetObject();
         if (!$jobObj) {
             // No more jobs available to run :'(
             break;
         }
         $success = false;
         if ($jobObj instanceof \SmashPig\Core\Jobs\RunnableJob) {
             try {
                 if ($jobObj->execute()) {
                     $success = true;
                 } else {
                     Logger::info("Job tells us that it did not successfully " . "execute. Sending to damaged message queue.");
                 }
             } catch (Exception $ex) {
                 Logger::error("Job threw exception. Sending to damaged message queue.", null, $ex);
             }
         } else {
             Logger::warning(get_class($jobObj) . " is not an instance of RunnableJob. " . "Could not execute and sending to damaged message queue.");
         }
         if ($success) {
             $successCount += 1;
         } else {
             $this->damagedDatastore->addObject($jobObj);
         }
         $this->datastore->queueAckObject();
     } while (time() - $startTime < $this->getOption('time-limit') && ++$messageCount < $this->getOption('max-messages'));
     $elapsedTime = time() - $startTime;
     Logger::info("Processed {$messageCount} ({$successCount} successful) jobs in {$elapsedTime} seconds.");
 }
 /**
  * @return Response
  */
 public static function process()
 {
     // Can go away once we require PHP 5.6
     ini_set('default_charset', 'UTF-8');
     // --- Get the request and response objects
     $request = Request::createFromGlobals();
     $response = new Response();
     $response->setPrivate();
     // --- Break the request into parts ---
     $uri = $request->query->get('p', '');
     $parts = explode('/', $uri);
     $request->query->remove('p');
     if (count($parts) < 2) {
         $response->setStatusCode(403, 'Cannot process this request: bad URI format. A configuration node and an action is required');
         return $response;
     }
     $view = array_shift($parts);
     $action = array_shift($parts);
     // --- Initialize core services ---
     $config = Configuration::createForView($view);
     Context::init($config);
     Logger::init($config->val('logging/root-context'), $config->val('logging/log-level'), $config, Context::get()->getContextId());
     if ($config->nodeExists('disabled') && $config->val('disabled')) {
         Logger::debug('403 will be given for disabled view.', $uri);
         $response->setStatusCode(403, "View '{$view}' disabled. Cannot continue.");
         return $response;
     }
     if ($config->nodeExists('charset')) {
         // recreate the request with a different input encoding
         // FIXME: This is only converting the POST values.  Also,
         // is there really no better way to do this?
         $decoded = rawurldecode($request->getContent());
         $content = mb_convert_encoding($decoded, 'UTF-8', $config->val('charset'));
         parse_str($content, $data);
         $request->request = new ParameterBag($data);
     }
     set_error_handler('\\SmashPig\\Core\\Http\\RequestHandler::lastChanceErrorHandler');
     set_exception_handler('\\SmashPig\\Core\\Http\\RequestHandler::lastChanceExceptionHandler');
     register_shutdown_function('\\SmashPig\\Core\\Http\\RequestHandler::shutdownHandler');
     // Check to make sure there's even a point to continuing
     Logger::info("Starting processing for request, configuration view: '{$view}', action: '{$action}'");
     if (!$config->nodeExists("endpoints/{$action}")) {
         Logger::debug('403 will be given for unknown action on inbound URL.', $uri);
         $response->setStatusCode(403, "Action '{$action}' not configured. Cannot continue.");
         return $response;
     }
     // Inform the request object of our security environment
     $trustedHeader = $config->val('security/ip-header-name');
     if ($trustedHeader) {
         $request->setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeader);
     }
     $trustedProxies = $config->val('security/ip-trusted-proxies');
     if ($trustedProxies) {
         $request->setTrustedProxies($trustedProxies);
     }
     // --- Actually get the endpoint object and start the request ---
     $endpointObj = $config->object("endpoints/{$action}");
     if ($endpointObj instanceof IHttpActionHandler) {
         $endpointObj->execute($request, $response);
     } else {
         $str = "Requested action '{$action}' does not implement a known handler. Cannot continue.";
         Logger::debug($str);
         $response->setStatusCode(500, $str);
     }
     $code = $response->getStatusCode();
     if ($code !== 200 && $code !== 302) {
         $response->setContent('');
     }
     return $response;
 }
 protected function createAdyenMsgObjFromItem(WSDL\NotificationRequestItem $item)
 {
     Logger::info('Creating Adyen message object from data.');
     $msg = AdyenMessage::getInstanceFromWSDL($item);
     if ($msg === false) {
         Logger::error('Listener message object could not be created. Unknown type!', $item);
         return false;
     } else {
         $className = get_class($msg);
         Logger::info("Listener message of type {$className} created.");
     }
     return $msg;
 }
 /**
  * Acknowledges and replaces, into the backing data store, the current queue message
  */
 public function queueIgnoreObject()
 {
     if (!$this->queueMsg) {
         throw new DataStoreTransactionException("No STOMP transaction currently in progress. Cannot requeue a non-existent message!");
     }
     Logger::debug("Acking STOMP message {$this->queueMsg->headers['message-id']}");
     $this->stompObj->ack($this->queueMsg);
     Logger::debug("Re-adding STOMP message to queue");
     $sent = $this->stompObj->send($this->queue_id, $this->queueMsg->body, $this->queueMsg->headers);
     if (!$sent) {
         Logger::error("Could not re-queue message to '{$this->queue_id}' on '{$this->uri}'", $this->queueMsg);
         throw new DataStoreException("Could not re-queue message to '{$this->queue_id}' on '{$this->uri}'");
     }
     $this->queueMsg = null;
     Logger::info("STOMP message requeued from '{$this->queue_id}' on '{$this->uri}'");
 }
 public function execute()
 {
     $this->config = Configuration::getDefaultConfig();
     if ($this->is_reject()) {
         // Returning false would cause it to go to the damaged queue, we
         // just want to forget about these.
         return true;
     }
     // XXX Why does everything get made into objects?
     $request = (array) $this->payload;
     // Determine message type.
     if (isset($request['txn_type'])) {
         $txn_type = $request['txn_type'];
     } elseif (isset($request['payment_status']) && in_array($request['payment_status'], array('Reversed', 'Refunded'))) {
         // refund, chargeback, or reversal
         $txn_type = 'refund';
     } else {
         throw new Exception('Invalid PayPal message: ' . json_encode($request));
     }
     $msg_type = null;
     foreach ($this->config->val('messages') as $type => $conf) {
         if (in_array($txn_type, $conf['txn_types'])) {
             $msg_type = $type;
         }
     }
     if (!$msg_type) {
         throw new Exception('Invalid PayPal message type: ' . $txn_type);
     }
     // Transform into new message.
     // FIXME this could just be an array, but we need compat with
     // keyedopaque* until activemq goes away
     $new_msg = new Message();
     // FIXME hacks because the recurring consumer doesn't want
     // a normalized message
     if ($msg_type === 'recurring') {
         foreach ($request as $key => $val) {
             $new_msg->{$key} = $val;
         }
     } else {
         $map = $this->config->val('var_map');
         foreach ($map as $rx => $tx) {
             if (array_key_exists($rx, $request)) {
                 $new_msg->{$tx} = $request[$rx];
             }
         }
         // FIXME: var map can't put one thing in two places
         if (isset($new_msg->contribution_tracking_id)) {
             $new_msg->order_id = $new_msg->contribution_tracking_id;
         }
         // FIXME represent special case as var_map config override?
         if ($msg_type === 'refund') {
             $new_msg->gateway_refund_id = $request['txn_id'];
             $new_msg->gross_currency = $request['mc_currency'];
             if (isset($new_msg->type) && $new_msg->type === 'chargeback_settlement') {
                 $new_msg->type = 'chargeback';
             } else {
                 $new_msg->type = $msg_type;
             }
         }
         // FIXME once recurring uses normalized msg it needs this too
         $new_msg->date = strtotime($new_msg->date);
     }
     $new_msg->gateway = 'paypal';
     SourceFields::addToMessage($new_msg);
     // Save to appropriate queue.
     $this->config->object('data-store/' . $msg_type)->push($new_msg);
     // FIXME random document formats
     if (substr($txn_type, 0, 7) === 'subscr_') {
         $log_id = "subscr_id:{$request['subscr_id']}";
     } else {
         $log_id = "txn_id:{$request['txn_id']}";
     }
     Logger::info("Message {$log_id} pushed to {$msg_type} queue.");
     // TODO It would be nice if push() returned something useful so we
     // could return something here too
     return true;
 }