/**
  * Validate the IPN notification
  *y gon
  * @param array                  $update_info like $_REQUEST
  * @param EE_Payment|EEI_Payment $payment
  * @return boolean
  */
 public function validate_ipn($update_info, $payment)
 {
     //allow us to skip validating IPNs with PayPal (useful for testing)
     if (apply_filters('FHEE__EEG_Paypal_Standard__validate_ipn__skip', false)) {
         return true;
     }
     //...otherwise, we actually don't care what the $update_info is, we need to look
     //at the request directly because we can't use $update_info because it has issues with quotes
     // Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
     // Instead, read raw POST data from the input stream.
     // @see https://gist.github.com/xcommerce-gists/3440401
     $raw_post_data = file_get_contents('php://input');
     $raw_post_array = explode('&', $raw_post_data);
     $update_info = array();
     foreach ($raw_post_array as $keyval) {
         $keyval = explode('=', $keyval);
         if (count($keyval) == 2) {
             $update_info[$keyval[0]] = urldecode($keyval[1]);
         }
     }
     // read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
     $req = 'cmd=_notify-validate';
     $get_magic_quotes_exists = function_exists('get_magic_quotes_gpc') ? true : false;
     foreach ($update_info as $key => $value) {
         if ($get_magic_quotes_exists && get_magic_quotes_gpc() == 1) {
             $value = urlencode(stripslashes($value));
         } else {
             $value = urlencode($value);
         }
         $req .= "&{$key}={$value}";
     }
     // HTTP POST the complete, unaltered IPN back to PayPal
     $response = wp_remote_post($this->_gateway_url, array('body' => $req, 'sslverify' => false, 'timeout' => 60, 'user-agent' => 'Event Espresso v' . EVENT_ESPRESSO_VERSION . '; ' . home_url(), 'httpversion' => '1.1'));
     // then check the response
     if (!is_wp_error($response) && array_key_exists('body', $response) && strcmp($response['body'], "VERIFIED") == 0) {
         return true;
     } else {
         // huh, something's wack... the IPN didn't validate. We must have replied to the IPN incorrectly,
         // or their API must have changed: http://www.paypalobjects.com/en_US/ebook/PP_OrderManagement_IntegrationGuide/ipn.html
         if (is_wp_error($response)) {
             $error_msg = sprintf(__('WP Error. Code: "%1$s", Message: "%2$s", Data: "%3$s"', 'event_espresso'), $response->get_error_code(), $response->get_error_message(), print_r($response->get_error_data, true));
         } elseif (is_array($response) && isset($response['body'])) {
             $error_msg = $response['body'];
         } else {
             $error_msg = print_r($response, true);
         }
         $payment->set_gateway_response(sprintf(__("IPN Validation failed! Paypal responded with '%s'", "event_espresso"), $error_msg));
         $payment->set_details(array('REQUEST' => $update_info, 'VALIDATION_RESPONSE' => $response));
         $payment->set_status(EEM_Payment::status_id_failed);
         // log the results
         $this->log(array('url' => $this->_process_response_url(), 'message' => $payment->gateway_response(), 'details' => $payment->details()), $payment);
         return false;
     }
 }
    /**
     * 	get_payment_row_html
     *
     *  @access 	public
     *  @param 	EE_Payment	$payment
     *  @return 	string
     */
    public function get_payment_row_html($payment = NULL)
    {
        $html = '';
        if ($payment instanceof EE_Payment) {
            if ($payment->payment_method() instanceof EE_Payment_Method && $payment->payment_method()->is_off_site() && $payment->status() === EEM_Payment::status_id_failed) {
                // considering the registrant has made it to the Thank You page,
                // any failed payments may actually be pending and the IPN is just slow
                // so let's
                $payment->set_status(EEM_Payment::status_id_pending);
            }
            $payment_declined_msg = $payment->STS_ID() === EEM_Payment::status_id_declined ? '<br /><span class="small-text">' . $payment->gateway_response() . '</span>' : '';
            $html .= '
				<tr>
					<td>
						' . $payment->timestamp() . '
					</td>
					<td>
						' . ($payment->payment_method() instanceof EE_Payment_Method ? $payment->payment_method()->name() : __('Unknown', 'event_espresso')) . '
					</td>
					<td class="jst-rght">
						' . EEH_Template::format_currency($payment->amount()) . '
					</td>
					<td class="jst-rght" style="line-height:1;">
						' . $payment->pretty_status(TRUE) . $payment_declined_msg . '
					</td>
				</tr>';
            do_action('AHEE__thank_you_page_payment_details_template__after_each_payment', $payment);
        }
        return $html;
    }
 /**
  * _process_cancelled_payments
  * just makes sure that the payment status gets updated correctly
  * so tha tan error isn't generated during payment validation
  *
  * @access private
  * @param EE_Payment $payment
  * @return EE_Payment | FALSE
  */
 private function _process_cancelled_payments($payment = NULL)
 {
     if (isset($_REQUEST['ee_cancel_payment']) && $payment instanceof EE_Payment && $payment->status() == EEM_Payment::status_id_failed) {
         $payment->set_status(EEM_Payment::status_id_cancelled);
     }
     return $payment;
 }