/**
  * Show the special page
  */
 protected function handleRequest()
 {
     $req = $this->getRequest();
     // TODO: Don't do that.
     $fake = $req->getBool('fake');
     $fail = $req->getBool('fail');
     if ($fake) {
         if ($fail) {
             $this->displayFailPage();
             return;
         } else {
             $go = ResultPages::getThankYouPage($this->adapter);
         }
         $this->getOutput()->addHTML("<br>Redirecting to page {$go}");
         $this->getOutput()->redirect($go);
         return;
     }
     $forbidden = false;
     $this->qs_oid = $req->getText('order_id', '');
     $this->qs_ref = $req->getText('REF', '');
     if ($this->qs_oid === '' && $this->qs_ref === '') {
         $forbidden = true;
         $f_message = 'No order ID in the Querystring.';
     } else {
         $result = $this->popout_if_iframe();
         if ($result) {
             return;
         }
     }
     $session_oid = $this->adapter->session_getData('Donor', 'order_id');
     if (is_null($session_oid) || $this->qs_oid !== $session_oid && strpos($this->qs_ref, (string) $session_oid) === false) {
         $forbidden = true;
         $f_message = "Requested order id not present in the session. (session_oid = '{$session_oid}')";
     }
     if ($forbidden) {
         $this->logger->error($this->qs_oid . " Resultswitcher: forbidden for reason: {$f_message}");
         wfHttpError(403, 'Forbidden', wfMessage('donate_interface-error-http-403')->text());
         return;
     }
     $this->setHeaders();
     $this->logger->info("Resultswitcher: OK to process Order ID: " . $this->qs_oid);
     // dispatch forms/handling
     if ($this->adapter->checkTokens()) {
         // Display form for the first time
         //this next block is for credit card coming back from GC. Only that. Nothing else, ever.
         if ($this->adapter->getData_Unstaged_Escaped('payment_method') === 'cc') {
             $sessionOrders = $req->getSessionData('order_status');
             if (!is_array($sessionOrders) || !isset($sessionOrders[$this->qs_oid]) || !is_array($sessionOrders[$this->qs_oid])) {
                 $result = $this->adapter->do_transaction('Confirm_CreditCard');
                 $session_info = array('data' => $result->getData(), 'message' => $result->getMessage(), 'errors' => $result->getErrors());
                 $sessionOrders[$this->qs_oid] = $session_info;
                 $sessionOrders[$this->qs_oid]['data']['count'] = 0;
             } else {
                 $sessionOrders = $req->getSessionData('order_status');
                 $sessionOrders[$this->qs_oid]['data']['count'] = $sessionOrders[$this->qs_oid]['data']['count'] + 1;
                 $this->logger->error("Resultswitcher: Multiple attempts to process. " . $sessionOrders[$this->qs_oid]['data']['count']);
                 $result = new PaymentTransactionResponse();
                 $result->setData($sessionOrders[$this->qs_oid]['data']);
                 $result->setMessage($sessionOrders[$this->qs_oid]['message']);
                 $result->setErrors($sessionOrders[$this->qs_oid]['errors']);
             }
             $req->setSessionData('order_status', $sessionOrders);
             $this->displayResultsForDebug($result);
             //do the switching between the... stuff.
             $status = $this->adapter->getFinalStatus();
             if ($status) {
                 switch ($status) {
                     case FinalStatus::COMPLETE:
                     case FinalStatus::PENDING:
                     case FinalStatus::PENDING_POKE:
                         $this->logger->info("Displaying thank you page for final status {$status}");
                         $go = ResultPages::getThankYouPage($this->adapter);
                         break;
                     case FinalStatus::FAILED:
                         $this->logger->info('Displaying fail page for final status failed.');
                         $this->displayFailPage();
                         return;
                 }
                 if ($go) {
                     $this->getOutput()->addHTML("<br>Redirecting to page {$go}");
                     $this->getOutput()->redirect($go);
                     return;
                 } else {
                     $this->logger->error("Resultswitcher: No redirect defined. Order ID: {$this->qs_oid}");
                 }
             } else {
                 $this->logger->error("Resultswitcher: No FinalStatus. Order ID: {$this->qs_oid}");
             }
         } else {
             $this->logger->error("Resultswitcher: Payment method is not cc. Order ID: {$this->qs_oid}");
         }
     } else {
         $this->logger->error("Resultswitcher: Token Check Failed. Order ID: {$this->qs_oid}");
     }
     $this->displayFailPage();
 }
コード例 #2
0
 /**
  * Called from do_transaction() in order to be able to deal with transactions that had
  * recoverable errors but that do require the entire transaction to be repeated.
  *
  * This function has the following extension hooks:
  *  * pre_process_<strtolower($transaction)>
  *    Called before the transaction is processed; intended to call setValidationAction()
  *    if the transaction should not be performed. Anti-fraud can be performed in this
  *    hook by calling $this->runAntifraudFilters().
  *
  *  * post_process_<strtolower($transaction)>
  *
  * @param string    $transaction Name of the transaction being performed
  * @param &string() $retryVars Reference to an array of variables that caused the
  *                  transaction to fail.
  *
  * @return PaymentTransactionResponse
  * @throws UnexpectedValueException
  */
 private final function do_transaction_internal($transaction, &$retryVars = null)
 {
     $this->debugarray[] = __FUNCTION__ . " is doing a {$transaction}.";
     //reset, in case this isn't our first time.
     $this->transaction_response = new PaymentTransactionResponse();
     $this->final_status = false;
     $this->setValidationAction('process', true);
     $errCode = null;
     /* --- Build the transaction string for cURL --- */
     try {
         $this->setCurrentTransaction($transaction);
         $this->executeIfFunctionExists('pre_process_' . $transaction);
         if ($this->getValidationAction() != 'process') {
             $this->logger->info("Failed pre-process checks for transaction type {$transaction}.");
             $this->transaction_response->setCommunicationStatus(false);
             $this->transaction_response->setMessage($this->getErrorMapByCodeAndTranslate('internal-0000'));
             $this->transaction_response->setErrors(array('internal-0000' => array('debugInfo' => "Failed pre-process checks for transaction type {$transaction}.", 'message' => $this->getErrorMapByCodeAndTranslate('internal-0000'), 'logLevel' => LogLevel::INFO)));
             return $this->transaction_response;
         }
         if (!$this->isBatchProcessor()) {
             // TODO: Maybe move this to the pre_process functions?
             $this->dataObj->saveContributionTrackingData();
         }
         $commType = $this->getCommunicationType();
         if ($commType === 'redirect') {
             //in the event that we have a redirect transaction that never displays the form,
             //save this most recent one before we leave.
             $this->session_pushFormName($this->getData_Unstaged_Escaped('ffname'));
             $this->transaction_response->setCommunicationStatus(true);
             // Build the redirect URL.
             $redirectUrl = $this->getProcessorUrl();
             $redirectParams = $this->buildRequestParams();
             if ($redirectParams) {
                 // Add GET parameters, if provided.
                 $redirectUrl .= '?' . http_build_query($redirectParams);
             }
             $this->transaction_response->setRedirect($redirectUrl);
             return $this->transaction_response;
         } elseif ($commType === 'xml') {
             $this->profiler->getStopwatch("buildRequestXML", true);
             // begin profiling
             $curlme = $this->buildRequestXML();
             // build the XML
             $this->profiler->saveCommunicationStats("buildRequestXML", $transaction);
             // save profiling data
         } elseif ($commType === 'namevalue') {
             $this->profiler->getStopwatch("buildRequestNameValueString", true);
             // begin profiling
             $curlme = $this->buildRequestNameValueString();
             // build the name/value pairs
             $this->profiler->saveCommunicationStats("buildRequestNameValueString", $transaction);
             // save profiling data
         } else {
             throw new UnexpectedValueException("Communication type of '{$commType}' unknown");
         }
     } catch (Exception $e) {
         $this->logger->critical('Malformed gateway definition. Cannot continue: Aborting.\\n' . $e->getMessage());
         $this->transaction_response->setCommunicationStatus(false);
         $this->transaction_response->setMessage($this->getErrorMapByCodeAndTranslate('internal-0001'));
         $this->transaction_response->setErrors(array('internal-0001' => array('debugInfo' => 'Malformed gateway definition. Cannot continue: Aborting.\\n' . $e->getMessage(), 'message' => $this->getErrorMapByCodeAndTranslate('internal-0001'), 'logLevel' => LogLevel::CRITICAL)));
         return $this->transaction_response;
     }
     /* --- Do the cURL request --- */
     $this->profiler->getStopwatch(__FUNCTION__, true);
     $txn_ok = $this->curl_transaction($curlme);
     if ($txn_ok === true) {
         // We have something to slice and dice.
         $this->logger->info("RETURNED FROM CURL:" . print_r($this->transaction_response->getRawResponse(), true));
         // Decode the response according to $this->getResponseType
         $formatted = $this->getFormattedResponse($this->transaction_response->getRawResponse());
         // Process the formatted response. This will then drive the result action
         try {
             $this->processResponse($formatted);
         } catch (ResponseProcessingException $ex) {
             $errCode = $ex->getErrorCode();
             $retryVars = $ex->getRetryVars();
             $this->transaction_response->addError($errCode, array('message' => $this->getErrorMapByCodeAndTranslate('internal-0001'), 'debugInfo' => $ex->getMessage(), 'logLevel' => LogLevel::ERROR));
         }
     } elseif ($txn_ok === false) {
         // nothing to process, so we have to build it manually
         $logMessage = 'Transaction Communication failed' . print_r($this->transaction_response, true);
         $this->logger->error($logMessage);
         $this->transaction_response->setCommunicationStatus(false);
         $this->transaction_response->setMessage($this->getErrorMapByCodeAndTranslate('internal-0002'));
         $this->transaction_response->setErrors(array('internal-0002' => array('debugInfo' => $logMessage, 'message' => $this->getErrorMapByCodeAndTranslate('internal-0002'), 'logLevel' => LogLevel::ERROR)));
     }
     // Log out how much time it took for the cURL request
     $this->profiler->saveCommunicationStats(__FUNCTION__, $transaction);
     if (!empty($retryVars)) {
         $this->logger->critical("{$transaction} Communication failed (errcode {$errCode}), will reattempt!");
         // Set this by key so that the result object still has all the cURL data
         $this->transaction_response->setCommunicationStatus(false);
         $this->transaction_response->setMessage($this->getErrorMapByCodeAndTranslate($errCode));
         $this->transaction_response->setErrors(array($errCode => array('debugInfo' => "{$transaction} Communication failed (errcode {$errCode}), will reattempt!", 'message' => $this->getErrorMapByCodeAndTranslate($errCode), 'logLevel' => LogLevel::CRITICAL)));
     }
     //if we have set errors by this point, the transaction is not okay
     $errors = $this->getTransactionErrors();
     if (!empty($errors)) {
         $txn_ok = false;
     }
     // If we have any special post-process instructions for this
     // transaction, do 'em.
     // NOTE: If you want your transaction to fire off the post-process
     // logic, you need to run $this->postProcessDonation in a function
     // called
     //	'post_process' . strtolower($transaction)
     // in the appropriate gateway object.
     if ($txn_ok && empty($retryVars)) {
         $this->executeIfFunctionExists('post_process_' . $transaction);
         if ($this->getValidationAction() != 'process') {
             $this->logger->info("Failed post-process checks for transaction type {$transaction}.");
             $this->transaction_response->setCommunicationStatus(false);
             $this->transaction_response->setMessage($this->getErrorMapByCodeAndTranslate('internal-0000'));
             $this->transaction_response->setErrors(array('internal-0000' => array('debugInfo' => "Failed post-process checks for transaction type {$transaction}.", 'message' => $this->getErrorMapByCodeAndTranslate('internal-0000'), 'logLevel' => LogLevel::INFO)));
             return $this->transaction_response;
         }
     }
     // log that the transaction is essentially complete
     $this->logger->info('Transaction complete.');
     if (!$this->isBatchProcessor()) {
         $this->debugarray[] = 'numAttempt = ' . $this->session_getData('numAttempt');
     }
     return $this->transaction_response;
 }