Completed
Push — master ( 2be24c...e22d32 )
by Mike
09:49
created

validate_transaction()   C

Complexity

Conditions 8
Paths 4

Size

Total Lines 40
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 40
rs 5.3846
cc 8
eloc 24
nc 4
nop 1
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 12 and the first side effect is on line 4.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit;
5
}
6
7
include_once( 'class-wc-gateway-paypal-response.php' );
8
9
/**
10
 * Handle PDT Responses from PayPal.
11
 */
12
class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
13
14
	/** @var string identity_token for PDT support */
15
	protected $identity_token;
16
17
	/**
18
	 * Constructor.
19
	 *
20
	 * @param bool $sandbox
21
	 * @param string $identity_token
22
	 */
23
	public function __construct( $sandbox = false, $identity_token = '' ) {
24
		add_action( 'woocommerce_thankyou_paypal', array( $this, 'check_response' ) );
25
26
		$this->identity_token = $identity_token;
27
		$this->sandbox        = $sandbox;
28
	}
29
30
	/**
31
	 * Validate a PDT transaction to ensure its authentic.
32
	 * @param  string $transaction
33
	 * @return bool|array False or result array
34
	 */
35
	protected function validate_transaction( $transaction ) {
36
		$pdt = array(
37
			'body' 			=> array(
38
				'cmd' => '_notify-synch',
39
				'tx'  => $transaction,
40
				'at'  => $this->identity_token,
41
			),
42
			'timeout' 		=> 60,
43
			'httpversion'   => '1.1',
44
			'user-agent'	=> 'WooCommerce/' . WC_VERSION
45
		);
46
47
		// Post back to get a response.
48
		$response = wp_safe_remote_post( $this->sandbox ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr', $pdt );
49
50
		if ( is_wp_error( $response ) || ! strpos( $response['body'], "SUCCESS" ) === 0 ) {
51
			return false;
52
		}
53
54
		// Parse transaction result data
55
		$transaction_result  = explode( "\n", $response['body'] );
56
		$transaction_results = array();
57
58
		foreach ( $transaction_result as $line ) {
59
			$line = explode( "=", $line );
60
			$key  = wc_clean( urldecode( $line[0] ) );
61
62
			if ( function_exists( 'iconv' ) ) {
63
				$value = wc_clean( iconv( 'windows-1252', 'utf-8', urldecode( isset( $line[1] ) ? $line[1] : '' ) ) );
64
			} else {
65
				$value = wc_clean( urldecode( isset( $line[1] ) ? $line[1] : '' ) );
66
			}
67
68
			$transaction_results[ $key ] = $value;
69
		}
70
71
		var_dump($transaction_results);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($transaction_results); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
72
73
		return $transaction_results;
74
	}
75
76
	/**
77
	 * Check Response for PDT.
78
	 */
79
	public function check_response() {
80
		if ( empty( $_REQUEST['cm'] ) || empty( $_REQUEST['tx'] ) || empty( $_REQUEST['st'] ) ) {
81
			return;
82
		}
83
84
		$order_id    = wc_clean( stripslashes( $_REQUEST['cm'] ) );
85
		$status      = wc_clean( strtolower( stripslashes( $_REQUEST['st'] ) ) );
86
		$amount      = wc_clean( stripslashes( $_REQUEST['amt'] ) );
87
		$transaction = wc_clean( stripslashes( $_REQUEST['tx'] ) );
88
89
		if ( ! ( $order = $this->get_paypal_order( $order_id ) ) || ! $order->has_status( 'pending' ) ) {
1 ignored issue
show
Bug introduced by
It seems like $order_id defined by wc_clean(stripslashes($_REQUEST['cm'])) on line 84 can also be of type array; however, WC_Gateway_Paypal_Response::get_paypal_order() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
90
			return false;
91
		}
92
93
		$transaction_result = $this->validate_transaction( $transaction );
1 ignored issue
show
Bug introduced by
It seems like $transaction defined by wc_clean(stripslashes($_REQUEST['tx'])) on line 87 can also be of type array; however, WC_Gateway_Paypal_PDT_Ha...:validate_transaction() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
94
95
		if ( $transaction_result && 'completed' === $status ) {
96
			if ( $order->get_total() != $amount ) {
97
				WC_Gateway_Paypal::log( 'Payment error: Amounts do not match (amt ' . $amount . ')' );
98
				$this->payment_on_hold( $order, sprintf( __( 'Validation error: PayPal amounts do not match (amt %s).', 'woocommerce' ), $amount ) );
99
			} else {
100
				$this->payment_complete( $order, $transaction,  __( 'PDT payment completed', 'woocommerce' ) );
1 ignored issue
show
Bug introduced by
It seems like $transaction defined by wc_clean(stripslashes($_REQUEST['tx'])) on line 87 can also be of type array; however, WC_Gateway_Paypal_Response::payment_complete() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
101
102
				// Log paypal transaction fee and other meta data.
103
				if ( ! empty( $transaction_result['mc_fee'] ) ) {
104
					update_post_meta( $order->id, 'PayPal Transaction Fee', $transaction_result['mc_fee'] );
105
				}
106
				if ( ! empty( $transaction_result['payer_email'] ) ) {
107
					update_post_meta( $order->id, 'Payer PayPal address', $transaction_result['payer_email'] );
108
				}
109
				if ( ! empty( $transaction_result['first_name'] ) ) {
110
					update_post_meta( $order->id, 'Payer first name', $transaction_result['first_name'] );
111
				}
112
				if ( ! empty( $transaction_result['last_name'] ) ) {
113
					update_post_meta( $order->id, 'Payer last name', $transaction_result['last_name'] );
114
				}
115
				if ( ! empty( $transaction_result['payment_type'] ) ) {
116
					update_post_meta( $order->id, 'Payment type', $transaction_result['payment_type'] );
117
				}
118
			}
119
		}
120
	}
121
}
122