コード例 #1
0
 /**
  * @param array $post_fields Associative array of fields posted to listener
  * @return bool
  */
 function validate($post_fields = array())
 {
     $url = Configuration::getDefaultConfig()->val('postback-url');
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_HEADER, 0);
     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     curl_setopt($ch, CURLOPT_POST, 1);
     // TODO we can put VERIFIED in config and generalize this
     // Always capture the cURL output
     $curlDebugLog = fopen('php://temp', 'r+');
     curl_setopt($ch, CURLOPT_VERBOSE, true);
     curl_setopt($ch, CURLOPT_STDERR, $curlDebugLog);
     $response = $this->curl($ch, $post_fields);
     // Read the logging output
     rewind($curlDebugLog);
     $logged = fread($curlDebugLog, 8192);
     fclose($curlDebugLog);
     Logger::debug("cURL verbose logging: {$logged}");
     if ($response === 'VERIFIED') {
         return true;
     } elseif ($response === 'INVALID') {
         return false;
     } else {
         // TODO: Log txn_id. This is annoying because of the random document formats.
         Logger::debug("Unknown response from PayPal IPN PB: [{$response}].\n" . "Verbose logging: {$logged}");
         // FIXME: The same thing happens for "INVALID" and totally broken
         // responses. Differentiate.
         return false;
     }
 }
コード例 #2
0
 /**
  * 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;
 }
コード例 #3
0
 /**
  * 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);
     }
 }
コード例 #4
0
 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}");
     }
 }
コード例 #5
0
 /**
  * @param WSDL\sendNotification $var
  *
  * @return WSDL\sendNotificationResponse
  */
 public function sendNotification(WSDL\sendNotification $var)
 {
     $messages = array();
     $respstring = "[failed]";
     if ($var->notification instanceof WSDL\NotificationRequest) {
         if ($var->notification->live) {
             Logger::info("Notification received from live server.");
         } else {
             Logger::info("Notification received from test server.");
         }
         // Create Messages from the hideous SOAPy mess
         if (is_array($var->notification->notificationItems->NotificationRequestItem)) {
             foreach ($var->notification->notificationItems->NotificationRequestItem as $item) {
                 $obj = $this->createAdyenMsgObjFromItem($item);
                 if ($obj !== false) {
                     $messages[] = $obj;
                 }
             }
         } else {
             $obj = $this->createAdyenMsgObjFromItem($var->notification->notificationItems->NotificationRequestItem);
             if ($obj !== false) {
                 $messages[] = $obj;
             }
         }
         $numItems = count($messages);
         Logger::info("Extracted {$numItems} from received message. Beginning processing loop.");
         // Now process each message to the best of our ability
         foreach ($messages as $msg) {
             if ($this->processMessage($msg)) {
                 Logger::debug("Message successfully processed. Moving along...");
             } else {
                 Logger::error("Message was not successfully processed!", $msg);
             }
         }
         Logger::info('Finished processing of IPN message, retuning accepted.');
         $respstring = '[accepted]';
     } else {
         Logger::warning("Received notification is not instance of NotificationRequest!", $var);
         $this->server->fault(500, 'Received notification is not instance of NotificationRequest!');
     }
     $response = new WSDL\sendNotificationResponse();
     $response->notificationResponse = $respstring;
     return $response;
 }
コード例 #6
0
 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}'");
     }
 }
コード例 #7
0
 /**
  * Creates an appropriate derived AdyenMessage instance from the object received
  * during the SOAP transaction.
  *
  * The magic here is looking at the eventCode field, normalizing it, and then
  * loading the class if it exists.
  *
  * @param \SmashPig\PaymentProviders\Adyen\WSDL\NotificationRequestItem $obj
  */
 public static function getInstanceFromWSDL(NotificationRequestItem $msgObj)
 {
     // Adyen events come in as UPPER_CASE_UNDERSCORE_DELIMITED, we turn this
     // into UpperCaseUnderscoreDelimited
     $className = implode('', array_map('ucwords', explode('_', strtolower($msgObj->eventCode))));
     $className = 'SmashPig\\PaymentProviders\\Adyen\\ExpatriatedMessages\\' . $className;
     if (class_exists($className)) {
         Logger::debug("Attempting construction of '{$className}'");
         $obj = new $className();
     } else {
         Logger::debug("Class not found '{$className}'");
         return false;
     }
     if ($obj instanceof AdyenMessage) {
         $obj->constructFromWSDL($msgObj);
     } else {
         throw new ListenerDataException("Instantiated object '{$className}' does not inherit from AdyenMessage'!");
     }
     return $obj;
 }
コード例 #8
0
 /**
  * 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;
 }
 protected function createIpnMessages($pendingMessage, $templates, $outputDir)
 {
     $oid = $pendingMessage['order_id'];
     $replacements = array('[[CURRENCY]]' => $pendingMessage['currency'], '[[AMOUNT]]' => $pendingMessage['gross'], '[[AMOUNT_IN_CENTS]]' => floatval($pendingMessage['gross']) * 100, '[[ORDER_ID]]' => $oid, '[[PROCESSOR_REF_1]]' => mt_rand(), '[[PROCESSOR_REF_2]]' => mt_rand());
     if ($this->getArgument('gateway') === 'astropay') {
         // ugly, but whatchagonnado?
         $replacements['[[ASTROPAY_SIGNATURE_SUCCESS]]'] = $this->getAstroPaySignature($pendingMessage, '9');
         $replacements['[[ASTROPAY_SIGNATURE_FAILURE]]'] = $this->getAstroPaySignature($pendingMessage, '8');
     }
     foreach ($templates as $template) {
         $fullPath = $this->templateDir . $template;
         if (is_dir($fullPath)) {
             continue;
         }
         $contents = file_get_contents($fullPath);
         $fname = $outputDir . '/' . preg_replace('/(.[a-z0-9]+)$/i', '.' . $oid . '\\1', $template);
         foreach ($replacements as $search => $replace) {
             $contents = str_replace($search, $replace, $contents);
         }
         file_put_contents($fname, $contents);
         Logger::debug("Wrote {$fname}.");
     }
 }
コード例 #10
0
 /**
  * @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;
 }
コード例 #11
0
 /**
  * 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}'");
 }
コード例 #12
0
 public static function getQueue($queueName)
 {
     $config = Context::get()->getConfiguration();
     $key = "data-store/{$queueName}";
     Logger::debug("Getting queue {$queueName} from key {$key}");
     // Get a reference to the config node so we can mess with it
     $node =& $config->val($key, true);
     if (empty($node['constructor-parameters']) || empty($node['constructor-parameters'][0]['queue'])) {
         Logger::debug("'queue' not set, defaulting to {$queueName}");
         $node['constructor-parameters'][0]['queue'] = $queueName;
     }
     return $config->object($key, true);
 }