Completed
Push — master ( 6989ee...e664f0 )
by Mike
07:24
created

validate_transaction()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 30
rs 8.439
cc 6
eloc 18
nc 3
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
			 $transaction_results[ wc_clean( urldecode( $line[0] ) ) ] = wc_clean( urldecode( isset( $line[1] ) ? $line[1] : '' ) );
61
		}
62
63
		return $transaction_results;
64
	}
65
66
	/**
67
	 * Check Response for PDT.
68
	 */
69
	public function check_response() {
70
		if ( empty( $_REQUEST['cm'] ) || empty( $_REQUEST['tx'] ) || empty( $_REQUEST['st'] ) ) {
71
			return;
72
		}
73
74
		$order_id    = wc_clean( stripslashes( $_REQUEST['cm'] ) );
75
		$status      = wc_clean( strtolower( stripslashes( $_REQUEST['st'] ) ) );
76
		$amount      = wc_clean( stripslashes( $_REQUEST['amt'] ) );
77
		$transaction = wc_clean( stripslashes( $_REQUEST['tx'] ) );
78
79
		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 74 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...
80
			return false;
81
		}
82
83
		$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 77 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...
84
85
		if ( $transaction_result && 'completed' === $status ) {
86
			if ( $order->get_total() != $amount ) {
87
				WC_Gateway_Paypal::log( 'Payment error: Amounts do not match (amt ' . $amount . ')' );
88
				$this->payment_on_hold( $order, sprintf( __( 'Validation error: PayPal amounts do not match (amt %s).', 'woocommerce' ), $amount ) );
89
			} else {
90
				$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 77 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...
91
92
				// Log paypal transaction fee and other meta data.
93
				if ( ! empty( $transaction_result['mc_fee'] ) ) {
94
					update_post_meta( $order->id, 'PayPal Transaction Fee', $transaction_result['mc_fee'] );
95
				}
96
				if ( ! empty( $transaction_result['payer_email'] ) ) {
97
					update_post_meta( $order->id, 'Payer PayPal address', $transaction_result['payer_email'] );
98
				}
99
				if ( ! empty( $transaction_result['first_name'] ) ) {
100
					update_post_meta( $order->id, 'Payer first name', $transaction_result['first_name'] );
101
				}
102
				if ( ! empty( $transaction_result['last_name'] ) ) {
103
					update_post_meta( $order->id, 'Payer last name', $transaction_result['last_name'] );
104
				}
105
				if ( ! empty( $transaction_result['payment_type'] ) ) {
106
					update_post_meta( $order->id, 'Payment type', $transaction_result['payment_type'] );
107
				}
108
			}
109
		}
110
	}
111
}
112