File "class-wc-gateway-paypal-ipn-handler.php"
Full path: /home/kosmetik/public_html/wp-content/plugins/woocommerce/includes/gateways/paypal/includes/class-wc-gateway-paypal-ipn-handler.php
File
size: 9.84 B
MIME-type: text/x-php
Charset: utf-8
Download Open Edit Advanced Editor Back
<?php
if (!defined('ABSPATH')) {
exit;
}
require_once dirname(__FILE__) . '/class-wc-gateway-paypal-response.php';
class WC_Gateway_Paypal_IPN_Handler extends WC_Gateway_Paypal_Response
{
protected $receiver_email;
public function __construct($sandbox = false, $receiver_email = '')
{
add_action('woocommerce_api_wc_gateway_paypal', array($this, 'check_response'));
add_action('valid-paypal-standard-ipn-request', array($this, 'valid_response'));
$this->receiver_email = $receiver_email;
$this->sandbox = $sandbox;
}
public function check_response()
{
if (!empty($_POST) && $this->validate_ipn()) {
$posted = wp_unslash($_POST);
do_action('valid-paypal-standard-ipn-request', $posted);
exit;
}
wp_die('PayPal IPN Request Failure', 'PayPal IPN', array('response' => 500));
}
public function valid_response($posted)
{
$order = !empty($posted['custom']) ? $this->get_paypal_order($posted['custom']) : false;
if ($order) {
$posted['payment_status'] = strtolower($posted['payment_status']);
WC_Gateway_Paypal::log('Found order #' . $order->get_id());
WC_Gateway_Paypal::log('Payment status: ' . $posted['payment_status']);
if (method_exists($this, 'payment_status_' . $posted['payment_status'])) {
call_user_func(array($this, 'payment_status_' . $posted['payment_status']), $order, $posted);
}
}
}
public function validate_ipn()
{
WC_Gateway_Paypal::log('Checking IPN response is valid');
$validate_ipn = wp_unslash($_POST);
$validate_ipn['cmd'] = '_notify-validate';
$params = array('body' => $validate_ipn, 'timeout' => 60, 'httpversion' => '1.1', 'compress' => false, 'decompress' => false, 'user-agent' => 'WooCommerce/' . WC()->version);
$response = wp_safe_remote_post($this->sandbox ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr', $params);
WC_Gateway_Paypal::log('IPN Response: ' . wc_print_r($response, true));
if (!is_wp_error($response) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && strstr($response['body'], 'VERIFIED')) {
WC_Gateway_Paypal::log('Received valid response from PayPal IPN');
return true;
}
WC_Gateway_Paypal::log('Received invalid response from PayPal IPN');
if (is_wp_error($response)) {
WC_Gateway_Paypal::log('Error response: ' . $response->get_error_message());
}
return false;
}
protected function validate_transaction_type($txn_type)
{
$accepted_types = array('cart', 'instant', 'express_checkout', 'web_accept', 'masspay', 'send_money', 'paypal_here');
if (!in_array(strtolower($txn_type), $accepted_types, true)) {
WC_Gateway_Paypal::log('Aborting, Invalid type:' . $txn_type);
exit;
}
}
protected function validate_currency($order, $currency)
{
if ($order->get_currency() !== $currency) {
WC_Gateway_Paypal::log('Payment error: Currencies do not match (sent "' . $order->get_currency() . '" | returned "' . $currency . '")');
$order->update_status('on-hold', sprintf(__('Validation error: PayPal currencies do not match (code %s).', 'woocommerce'), $currency));
exit;
}
}
protected function validate_amount($order, $amount)
{
if (number_format($order->get_total(), 2, '.', '') !== number_format($amount, 2, '.', '')) {
WC_Gateway_Paypal::log('Payment error: Amounts do not match (gross ' . $amount . ')');
$order->update_status('on-hold', sprintf(__('Validation error: PayPal amounts do not match (gross %s).', 'woocommerce'), $amount));
exit;
}
}
protected function validate_receiver_email($order, $receiver_email)
{
if (strcasecmp(trim($receiver_email), trim($this->receiver_email)) !== 0) {
WC_Gateway_Paypal::log("IPN Response is for another account: {$receiver_email}. Your email is {$this->receiver_email}");
$order->update_status('on-hold', sprintf(__('Validation error: PayPal IPN response from a different email address (%s).', 'woocommerce'), $receiver_email));
exit;
}
}
protected function payment_status_completed($order, $posted)
{
if ($order->has_status(wc_get_is_paid_statuses())) {
WC_Gateway_Paypal::log('Aborting, Order #' . $order->get_id() . ' is already complete.');
exit;
}
$this->validate_transaction_type($posted['txn_type']);
$this->validate_currency($order, $posted['mc_currency']);
$this->validate_amount($order, $posted['mc_gross']);
$this->validate_receiver_email($order, $posted['receiver_email']);
$this->save_paypal_meta_data($order, $posted);
if ('completed' === $posted['payment_status']) {
if ($order->has_status('cancelled')) {
$this->payment_status_paid_cancelled_order($order, $posted);
}
if (!empty($posted['mc_fee'])) {
$order->add_meta_data('PayPal Transaction Fee', wc_clean($posted['mc_fee']));
}
$this->payment_complete($order, !empty($posted['txn_id']) ? wc_clean($posted['txn_id']) : '', __('IPN payment completed', 'woocommerce'));
} else {
if ('authorization' === $posted['pending_reason']) {
$this->payment_on_hold($order, __('Payment authorized. Change payment status to processing or complete to capture funds.', 'woocommerce'));
} else {
$this->payment_on_hold($order, sprintf(__('Payment pending (%s).', 'woocommerce'), $posted['pending_reason']));
}
}
}
protected function payment_status_pending($order, $posted)
{
$this->payment_status_completed($order, $posted);
}
protected function payment_status_failed($order, $posted)
{
$order->update_status('failed', sprintf(__('Payment %s via IPN.', 'woocommerce'), wc_clean($posted['payment_status'])));
}
protected function payment_status_denied($order, $posted)
{
$this->payment_status_failed($order, $posted);
}
protected function payment_status_expired($order, $posted)
{
$this->payment_status_failed($order, $posted);
}
protected function payment_status_voided($order, $posted)
{
$this->payment_status_failed($order, $posted);
}
protected function payment_status_paid_cancelled_order($order, $posted)
{
$this->send_ipn_email_notification(sprintf(__('Payment for cancelled order %s received', 'woocommerce'), '<a class="link" href="' . esc_url($order->get_edit_order_url()) . '">' . $order->get_order_number() . '</a>'), sprintf(__('Order #%s has been marked paid by PayPal IPN, but was previously cancelled. Admin handling required.', 'woocommerce'), $order->get_order_number()));
}
protected function payment_status_refunded($order, $posted)
{
if ($order->get_total() === wc_format_decimal($posted['mc_gross'] * -1, wc_get_price_decimals())) {
$order->update_status('refunded', sprintf(__('Payment %s via IPN.', 'woocommerce'), strtolower($posted['payment_status'])));
$this->send_ipn_email_notification(sprintf(__('Payment for order %s refunded', 'woocommerce'), '<a class="link" href="' . esc_url($order->get_edit_order_url()) . '">' . $order->get_order_number() . '</a>'), sprintf(__('Order #%1$s has been marked as refunded - PayPal reason code: %2$s', 'woocommerce'), $order->get_order_number(), $posted['reason_code']));
}
}
protected function payment_status_reversed($order, $posted)
{
$order->update_status('on-hold', sprintf(__('Payment %s via IPN.', 'woocommerce'), wc_clean($posted['payment_status'])));
$this->send_ipn_email_notification(sprintf(__('Payment for order %s reversed', 'woocommerce'), '<a class="link" href="' . esc_url($order->get_edit_order_url()) . '">' . $order->get_order_number() . '</a>'), sprintf(__('Order #%1$s has been marked on-hold due to a reversal - PayPal reason code: %2$s', 'woocommerce'), $order->get_order_number(), wc_clean($posted['reason_code'])));
}
protected function payment_status_canceled_reversal($order, $posted)
{
$this->send_ipn_email_notification(sprintf(__('Reversal cancelled for order #%s', 'woocommerce'), $order->get_order_number()), sprintf(__('Order #%1$s has had a reversal cancelled. Please check the status of payment and update the order status accordingly here: %2$s', 'woocommerce'), $order->get_order_number(), esc_url($order->get_edit_order_url())));
}
protected function save_paypal_meta_data($order, $posted)
{
if (!empty($posted['payment_type'])) {
update_post_meta($order->get_id(), 'Payment type', wc_clean($posted['payment_type']));
}
if (!empty($posted['txn_id'])) {
update_post_meta($order->get_id(), '_transaction_id', wc_clean($posted['txn_id']));
}
if (!empty($posted['payment_status'])) {
update_post_meta($order->get_id(), '_paypal_status', wc_clean($posted['payment_status']));
}
}
protected function send_ipn_email_notification($subject, $message)
{
$new_order_settings = get_option('woocommerce_new_order_settings', array());
$mailer = WC()->mailer();
$message = $mailer->wrap_message($subject, $message);
$woocommerce_paypal_settings = get_option('woocommerce_paypal_settings');
if (!empty($woocommerce_paypal_settings['ipn_notification']) && 'no' === $woocommerce_paypal_settings['ipn_notification']) {
return;
}
$mailer->send(!empty($new_order_settings['recipient']) ? $new_order_settings['recipient'] : get_option('admin_email'), strip_tags($subject), $message);
}
}