protected function __construct() { $config = Context::get()->getConfiguration(); if (!$this->getDatabase()) { $this->setDatabase($config->object($this->getConfigKey())); } }
public function setAccount($account) { require_once 'WSDL/Payment.php'; $this->account = $account; $c = Context::get()->getConfiguration(); $this->soapClient = new WSDL\Payment($c->val('payment-provider/adyen/payments-wsdl'), array('cache_wsdl' => WSDL_CACHE_BOTH, 'login' => $c->val("payment-provider/adyen/accounts/{$this->account}/ws-username"), 'password' => $c->val("payment-provider/adyen/accounts/{$this->account}/ws-password"))); }
public function setUp() { parent::setUp(); $this->config = AdyenTestConfiguration::createWithSuccessfulApi(); Context::initWithLogger($this->config); $this->jobQueue = $this->config->object('data-store/jobs-adyen'); $this->jobQueue->createTable('jobs-adyen'); }
public function setUp() { parent::setUp(); $config = SmashPigDatabaseTestConfiguration::instance(); Context::initWithLogger($config); $this->db = DamagedDatabase::get(); $this->db->createTable(); }
public function execute() { $context = Context::get(); $config = $context->getConfiguration(); $values = $config->val('/'); $yaml = Yaml::dump($values); print $yaml; }
public function setUp() { parent::setUp(); $this->config = AdyenTestConfiguration::createWithSuccessfulApi(); Context::initWithLogger($this->config); $this->jobQueue = BaseQueueConsumer::getQueue('jobs-adyen'); $this->jobQueue->createTable('jobs-adyen'); }
public static function addToMessage($message) { $message->source_name = 'SmashPig'; $message->source_type = 'listener'; $message->source_host = gethostname(); $message->source_run_id = getmypid(); $message->source_version = Context::get()->getSourceRevision(); $message->source_enqueued_time = time(); }
public function setUp() { parent::setUp(); Context::initWithLogger(QueueTestConfiguration::instance()); $this->queue = BaseQueueConsumer::getQueue('test'); $this->queue->createTable('test'); $damagedDb = DamagedDatabase::get(); $damagedDb->createTable(); $this->damaged = $damagedDb->getDatabase(); }
public function setUp() { parent::setUp(); $this->config = AdyenTestConfiguration::createWithSuccessfulApi(); Context::initWithLogger($this->config); $this->pendingDatabase = PendingDatabase::get(); $this->pendingMessage = json_decode(file_get_contents(__DIR__ . '/../Data/pending.json'), true); $this->pendingDatabase->storeMessage($this->pendingMessage); $this->antifraudQueue = BaseQueueConsumer::getQueue('payments-antifraud'); }
public function setUp() { parent::setUp(); $this->config = AdyenTestConfiguration::createWithSuccessfulApi(); Context::initWithLogger($this->config); $this->pendingDatabase = PendingDatabase::get(); $this->pendingMessage = json_decode(file_get_contents(__DIR__ . '/../Data/pending.json'), true); $this->pendingMessage['captured'] = true; $this->pendingDatabase->storeMessage($this->pendingMessage); }
public function setUp() { parent::setUp(); $this->setMwGlobals(array('wgDonationInterfaceOrphanCron' => array('enable' => true, 'target_execute_time' => self::TARGET_EXECUTE_TIME, 'time_buffer' => self::TIME_BUFFER), 'wgGlobalCollectGatewayEnabled' => true, 'wgDonationInterfaceGatewayAdapters' => array('globalcollect' => 'TestingGlobalCollectOrphanAdapter', 'globalcollect_orphan' => 'TestingGlobalCollectOrphanAdapter'))); $config = SmashPigDatabaseTestConfiguration::instance(); Context::init($config); $this->pendingDb = PendingDatabase::get(); // Create the schema. $this->pendingDb->createTable(); }
public function setUp() { parent::setUp(); $config = SmashPigDatabaseTestConfiguration::instance(); Context::initWithLogger($config); $this->pendingDb = PendingDatabase::get(); $this->pendingDb->createTable(); $this->paymentsInitialDb = PaymentsInitialDatabase::get(); $this->paymentsInitialDb->createTable(); }
public function setUp() { parent::setUp(); // Merge db and queue test configs. $config = TestingConfiguration::loadConfigWithFileOverrides(array(__DIR__ . '/data/config_smashpig_db.yaml', __DIR__ . '/data/config_queue.yaml')); Context::initWithLogger($config); $this->pendingDb = PendingDatabase::get(); $this->pendingDb->createTable(); $this->paymentsInitialDb = PaymentsInitialDatabase::get(); $this->paymentsInitialDb->createTable(); }
public function setUp() { parent::setUp(); $this->config = PayPalTestConfiguration::get(); // php-queue\PDO complains about pop() from non-existent table $this->config->object('data-store/jobs-paypal')->createTable('jobs-paypal'); Context::initWithLogger($this->config); foreach (self::$message_data as $file => $type) { self::$messages[] = array('type' => $type, 'payload' => json_decode(file_get_contents(__DIR__ . '/../Data/' . $file), true)); } }
public function setUp() { parent::setUp(); chdir(__DIR__ . '/..'); // So the mock client can find its response files $config = AmazonTestConfiguration::instance(); Context::initWithLogger($config); $this->mockClient = $config->object('payments-client', true); $this->mockClient->calls = array(); $this->mockClient->returns = array(); $this->mockClient->exceptions = array(); }
public function parseFile($path) { $config = Context::get()->getConfiguration(); $fileTypes = $config->val('audit/file-types'); $data = array(); foreach ($fileTypes as $type) { if ($type::isMine($path)) { $parser = new $type(); $data = $parser->parse($path); } } return $data; }
public function execute(ListenerMessage $msg) { $destinationQueue = $msg->getDestinationQueue(); if ($destinationQueue) { $queue = Context::get()->getConfiguration()->object("data-store/{$destinationQueue}"); $queueMsg = $msg->normalizeForQueue(); SourceFields::addToMessage($queueMsg); $queue->push($queueMsg); } else { $class = get_class($msg); Logger::warning("Ignoring message of type {$class}", $msg); } return true; }
public function download() { $this->ensureAndScanFolder($this->archivePath); $this->ensureAndScanFolder($this->downloadPath); $this->reportsClient = Context::get()->getConfiguration()->object('reports-client', true); Logger::info('Getting report list'); $startDate = new DateTime("-{$this->days} days", new DateTimeZone('UTC')); $list = $this->reportsClient->getReportList(array('available_from_date' => $startDate->format(DateTime::ATOM), 'max_count' => 100, 'report_type_list' => array(ReportsClient::OFFAMAZONPAYMENTS_SETTLEMENT, ReportsClient::OFFAMAZONPAYMENTS_REFUND)))->toArray(); foreach ($list['GetReportListResult']['ReportInfo'] as $reportInfo) { // If you're planning to download more than 15 reports at a time, be // aware that the client will handle throttling by default, retrying // up to four times with successively longer wait times. $this->downloadReport($reportInfo); } }
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; }
/** * 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"); }
/** * Adds an object to the persistent data store. * * @param KeyedOpaqueStorableObject $obj * * @throws DataStoreException if the message could not be stored. * @return null */ public function addObject(KeyedOpaqueStorableObject $obj) { $keys = $obj->getObjectKeys(); $objFileName = $this->constructFileName(Context::get()->getContextId(), $keys, $this->insertCount++); $objFsPath = $this->basePath . '/objects/' . $objFileName; /* --- Create the root object file --- */ if (file_exists($objFsPath) || ($fptr = fopen($objFsPath, 'xb')) === false) { throw new DataStoreException("Could not add object to store! Fully qualified key '{$objFileName}' already exists!"); } fwrite($fptr, get_class($obj)); fwrite($fptr, "\n"); fwrite($fptr, $obj->toJson()); fclose($fptr); /* === Create the helper linking files === */ /* --- Class file first --- */ $this->addKeyedLinkingFile('class', get_class($obj), $objFileName, $objFsPath); /* --- Everything else --- */ foreach ($keys as $key => $value) { $this->addKeyedLinkingFile($key, $value, $objFileName, $objFsPath); } }
/** * 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; }
public static function findRefundParentId($refundId) { $config = Context::get()->getConfiguration(); $client = $config->object('payments-client', true); // The order reference ID is the first 19 characters of the refund ID $orderReferenceId = substr($refundId, 0, 19); $getDetailsResult = $client->getOrderReferenceDetails(array('amazon_order_reference_id' => $orderReferenceId))->toArray(); if (!empty($getDetailsResult['Error'])) { throw new SmashPigException($getDetailsResult['Error']['Message']); } // The order reference details should contain an IdList with all of the // authorizations that have been made against the order reference. We // should only ever have one authorization per order reference. $details = $getDetailsResult['GetOrderReferenceDetailsResult']['OrderReferenceDetails']; if (!isset($details['IdList']) || !isset($details['IdList']['member'])) { throw new SmashPigException("No authorizations found for order reference {$orderReferenceId}!"); } $authorizationIds = (array) $details['IdList']['member']; // Check the status of each authorization against the order reference foreach ($authorizationIds as $id) { $authResult = $client->getAuthorizationDetails(array('amazon_authorization_id' => $id))->toArray(); if (!empty($authResult['Error'])) { throw new SmashPigException($authResult['Error']['Message']); } $details = $authResult['GetAuthorizationDetailsResult']['AuthorizationDetails']; $state = $details['AuthorizationStatus']['State']; // Once we successfully capture payment against an authorization, it // transitions to the 'Closed' state. Failed attempts are 'Declined' if ($state === 'Closed') { // And guess what? The authorization ID is exactly the same as the // capture ID (which we store as the gateway txn id), with one letter // changed. $captureId = substr($id, 0, 20) . 'C' . substr($id, 21); return $captureId; } } throw new SmashPigException("No successful authorizations found for order reference {$orderReferenceId}!"); }
public function execute() { $this->logger = new TaggedLogger(__CLASS__); $c = Context::get()->getConfiguration(); // Construct the temporary file path $fileName = basename($this->reportUrl); $this->downloadLoc = $c->val("payment-provider/adyen/accounts/{$this->account}/report-location") . '/' . $fileName; $user = $c->val("payment-provider/adyen/accounts/{$this->account}/report-username"); $pass = $c->val("payment-provider/adyen/accounts/{$this->account}/report-password"); $this->logger->info("Beginning report download from {$this->reportUrl} using username {$user} into {$this->downloadLoc}"); $fp = fopen($this->downloadLoc, 'w'); if (!$fp) { $str = "Could not open {$this->downloadLoc} for writing! Will not download report."; $this->logger->error($str); throw new SmashPigException($str); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->reportUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_USERPWD, "{$user}:{$pass}"); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($result === false) { $this->logger->error("Could not download report due to cURL error {$error}"); throw new SmashPigException("Could not download report."); } elseif ($httpCode !== 200) { $this->logger->error("Report downloaded(?), but with incorrect HTTP code: {$httpCode}"); throw new SmashPigException("Could not download report."); } return true; }
/** * Sets the current context, returning the displaced context * @param Context $c * @return Context */ public static function set(Context $c = null) { $old = Context::$instance; Context::$instance = $c; return $old; }
/** * @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; }
if (!defined('RUN_MAINTENANCE_IF_MAIN')) { print "This file must be included after MaintenanceBase.php\n"; exit(1); } // Wasn't included from the file scope, halt execution (probably wanted the class) if (!MaintenanceBase::shouldExecute()) { return; } if (!$maintClass || !class_exists($maintClass)) { print "Cannot find maintenance class '{$maintClass}'; have you remembered to set it?\n"; exit(1); } // Get an object to start us off $maintenance = new $maintClass(); if ($maintenance instanceof MaintenanceBase) { // Perform setup $maintenance->setup(); // Now that we have a config node, check for disablement $config = Context::get()->getConfiguration(); if ($config->nodeExists('disabled') && $config->val('disabled')) { print 'Processor disabled, will not execute.'; exit(1); } $retval = $maintenance->execute(); if ($retval) { exit((int) $retval); } } else { print "{$maintClass} is not a derivative of MaintenanceBase. Cannot execute.\n"; exit(1); }
/** * Set a test configuration and initialize the context * * @param string $configNode node to use for configuration overrides * @param string $configPath path to configuration override file * @return Configuration */ function setConfig($configNode = 'default', $configPath = null) { $config = Configuration::createForViewWithOverrideFile($configNode, $configPath); Context::initWithLogger($config); return $config; }
/** * Get the value of a given option. Will return the value at configuration node * $defaultNode if the node exists and the option was not explicitly set, else * will return the default set when the option was created. * * @param string $name Name of the option to retrieve * @param string $defaultNode Config node holding override for the option * * @return mixed Value of the option or null if no default was provided */ protected function getOptionOrConfig($name, $defaultNode) { $config = Context::get()->getConfiguration(); if ($config->nodeExists($defaultNode)) { $default = $config->val($defaultNode); } else { $default = null; } return $this->getOption($name, $default); }
/** * Monolithic function to send an email! * * Several configuration nodes are required for this function: * email/from-address Default address for the From header * email/bounce-address Default address to use when VERPing the email. * IE: bounce+$1@contoso.com * email/archive-addresses A list of addresses to always BCC when this function is used * * @param string $to Email address of recipient * @param string $subject Subject line of email * @param string $textBody Non HTML text of email (fallback text if $htmlBody is defined) * @param null|string|array $from Email address of sender, if null is the value of the configuration * node 'email/from-address'. If passed as an array it is expected that * index 0 is the address and index 1 is the friendly name of the address. * @param null|string $replyTo Address that recipient will reply to. If null will be set from the value * of $from. * @param null|string $htmlBody HTML text of the email * @param array $attach Paths to any attachments. These can have any legal PHP file descriptor. * @param null|string|array $cc Carbon-Copy addresses. * @param null|string|array $bcc Blind carbon-copy addresses. If specified these will always be in addition * to any archival addresses specified by the 'email/archive-addresses' * configuration node. * @param bool|string $useVerp If true will set the MAIL FROM to the value specified under configuration * node 'email/bounce-address'. This can be overriden if a string is passed * instead of strict true. In either case, '$1' will be replaced by the * first $to address, RFC-3986 encoded. * * @returns bool True if successfully sent. False if a PHPMailer exception occurred. Exceptions are logged at the * warning level. */ public static function sendEmail($to, $subject, $textBody, $from = null, $replyTo = null, $htmlBody = null, $attach = array(), $cc = null, $bcc = null, $useVerp = true) { $config = Context::get()->getConfiguration(); $mailer = static::mailbaseFactory(); try { $to = (array) $to; $cc = (array) $cc; $bcc = (array) $bcc; $archives = (array) $config->val('email/archive-addresses'); array_walk($to, function ($value, $key) use($mailer) { $mailer->AddAddress($value); }); array_walk($cc, function ($value, $key) use($mailer) { $mailer->AddCC($value); }); array_walk($bcc, function ($value, $key) use($mailer) { $mailer->AddBCC($value); }); array_walk($archives, function ($value, $key) use($mailer) { $mailer->AddBCC($value); }); array_walk($attach, function ($value, $key) use($mailer) { $mailer->AddAttachment($value); }); // Set the from address if (!$from) { $from = $config->val('email/from-address'); } if (is_array($from)) { $mailer->SetFrom($from[0], $from[1]); } else { $mailer->SetFrom((string) $from); } // Only add reply to manually if requested, otherwise it's set when we call SetFrom if ($replyTo) { $mailer->AddReplyTo($replyTo); } // Set subject and body $mailer->Subject = $subject; if ($htmlBody) { $mailer->MsgHTML($htmlBody); $mailer->AltBody = $textBody; } else { $mailer->Body = $textBody; } // We replace $1 in email/bounce-address or useVerp if string to create the bounce addr if ($useVerp) { $sourceAddr = (array) $to; $sourceAddr = rawurlencode($sourceAddr[0]); if (is_string($useVerp)) { $bounceAddr = $useVerp; } else { $bounceAddr = $config->val('email/bounce-address'); } $bounceAddr = str_replace('$1', $sourceAddr, $bounceAddr); $mailer->Sender = $bounceAddr; } $mailer->Send(); } catch (\phpmailerException $ex) { $toStr = implode(", ", $to); Logger::warning("Could not send email to {$toStr}. PHP Mailer had exception.", null, $ex); return false; } return true; }