1
|
|
|
<?php |
|
|
|
|
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); |
|
|
|
|
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' ) ) { |
|
|
|
|
90
|
|
|
return false; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
$transaction_result = $this->validate_transaction( $transaction ); |
|
|
|
|
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' ) ); |
|
|
|
|
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
|
|
|
|
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.