コード例 #1
0
 /**
  * Sends a curl request to the gateway server, and gets a response.
  * Saves that response to the transaction_response's rawResponse;
  * @param string $data the raw data we want to curl up to a server somewhere.
  * Should have been constructed with either buildRequestNameValueString, or
  * buildRequestXML.
  * @return boolean true if the communication was successful and there is a
  * parseable response, false if there was a fundamental communication
  * problem. (timeout, bad URL, etc.)
  */
 protected function curl_transaction($data)
 {
     $this->profiler->getStopwatch(__FUNCTION__, true);
     // Basic variable init
     $retval = false;
     // By default return that we failed
     $gatewayName = self::getGatewayName();
     $email = $this->getData_Unstaged_Escaped('email');
     /**
      * This log line is pretty important. Usually when a donor contacts us
      * saying that they have experienced problems donating, the first thing
      * we have to do is associate a gateway transaction ID and ctid with an
      * email address. If the cURL function fails, we lose the ability to do
      * that association outside of this log line.
      */
     $this->logger->info("Initiating cURL for donor {$email}");
     // Initialize cURL and construct operation (also run filter)
     $ch = curl_init();
     $filterResult = $this->runSessionVelocityFilter();
     if ($filterResult == false) {
         return false;
     }
     // assign header data necessary for the curl_setopt() function
     $headers = $this->getCurlBaseHeaders();
     $headers[] = 'Content-Length: ' . strlen($data);
     $curl_opts = $this->getCurlBaseOpts();
     $curl_opts[CURLOPT_HTTPHEADER] = $headers;
     $curl_opts[CURLOPT_POSTFIELDS] = $data;
     // Always capture the cURL output
     $curlDebugLog = fopen('php://temp', 'r+');
     $curl_opts[CURLOPT_STDERR] = $curlDebugLog;
     $enableCurlVerboseLogging = $this->getGlobal('CurlVerboseLog');
     curl_setopt_array($ch, $curl_opts);
     // As suggested in the PayPal developer forum sample code, try more than once to get a
     // response in case there is a general network issue
     $continue = true;
     $tries = 0;
     $curl_response = false;
     $loopCount = $this->getGlobal('RetryLoopCount');
     do {
         $this->logger->info("Preparing to send {$this->getCurrentTransaction()} transaction to {$gatewayName}");
         // Execute the cURL operation
         $curl_response = $this->curl_exec($ch);
         // Always read the verbose output
         rewind($curlDebugLog);
         $logged = fread($curlDebugLog, 4096);
         if ($curl_response !== false) {
             // The cURL operation was at least successful, what happened in it?
             // Only log verbose output on success if configured to do so
             if ($enableCurlVerboseLogging) {
                 $this->logger->info("cURL verbose logging: {$logged}");
             }
             $headers = $this->curl_getinfo($ch);
             $httpCode = $headers['http_code'];
             switch ($httpCode) {
                 case 200:
                     // Everything is AWESOME
                     $continue = false;
                     $this->logger->debug("Successful transaction to {$gatewayName}");
                     $this->transaction_response->setRawResponse($curl_response);
                     $retval = true;
                     break;
                 case 400:
                     // Oh noes! Bad request.. BAD CODE, BAD BAD CODE!
                     $continue = false;
                     $this->logger->error("{$gatewayName} returned (400) BAD REQUEST: {$curl_response}");
                     // Even though there was an error, set the results. Amazon at least gives
                     // us useful XML return
                     $this->transaction_response->setRawResponse($curl_response);
                     $retval = true;
                     break;
                 case 403:
                     // Hmm, forbidden? Maybe if we ask it nicely again...
                     $continue = true;
                     $this->logger->alert("{$gatewayName} returned (403) FORBIDDEN: {$curl_response}");
                     break;
                 default:
                     // No clue what happened... break out and log it
                     $continue = false;
                     $this->logger->error("{$gatewayName} failed remotely and returned ({$httpCode}): {$curl_response}");
                     break;
             }
         } else {
             // Well the cURL transaction failed for some reason or another. Try again!
             $continue = true;
             $errno = $this->curl_errno($ch);
             $err = curl_error($ch);
             $this->logger->alert("cURL transaction to {$gatewayName} failed: ({$errno}) {$err}.  " . "cURL verbose logging: {$logged}");
         }
         $tries++;
         if ($tries >= $loopCount) {
             $continue = false;
         }
         if ($continue) {
             // If we're going to try again, log timing for this particular curl attempt and reset
             $this->profiler->saveCommunicationStats(__FUNCTION__, $this->getCurrentTransaction(), "cURL problems");
             $this->profiler->getStopwatch(__FUNCTION__, true);
             rewind($curlDebugLog);
         }
     } while ($continue);
     // End while cURL transaction hasn't returned something useful
     // Clean up and return
     curl_close($ch);
     fclose($curlDebugLog);
     $log_results = array('result' => $curl_response, 'headers' => $headers);
     $this->profiler->saveCommunicationStats(__FUNCTION__, $this->getCurrentTransaction(), "Response: " . print_r($log_results, true));
     return $retval;
 }