1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
4
|
|
|
exit; |
5
|
|
|
} |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Handles Refunds and other API requests such as capture. |
9
|
|
|
* @since 2.7.0 |
10
|
|
|
*/ |
11
|
|
|
class WC_Gateway_Paypal_API_Handler { |
12
|
|
|
|
13
|
|
|
/** @var string API Username */ |
14
|
|
|
public static $api_username; |
15
|
|
|
|
16
|
|
|
/** @var string API Password */ |
17
|
|
|
public static $api_password; |
18
|
|
|
|
19
|
|
|
/** @var string API Signature */ |
20
|
|
|
public static $api_signature; |
21
|
|
|
|
22
|
|
|
/** @var bool Sandbox */ |
23
|
|
|
public static $sandbox = false; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Get capture request args. |
27
|
|
|
* See https://developer.paypal.com/docs/classic/api/merchant/DoCapture_API_Operation_NVP/. |
28
|
|
|
* @param WC_Order $order |
29
|
|
|
* @param float $amount |
30
|
|
|
* @return array |
31
|
|
|
*/ |
32
|
|
|
public static function get_capture_request( $order, $amount = null ) { |
33
|
|
|
$request = array( |
34
|
|
|
'VERSION' => '84.0', |
35
|
|
|
'SIGNATURE' => self::$api_signature, |
36
|
|
|
'USER' => self::$api_username, |
37
|
|
|
'PWD' => self::$api_password, |
38
|
|
|
'METHOD' => 'DoCapture', |
39
|
|
|
'AUTHORIZATIONID' => $order->get_transaction_id(), |
40
|
|
|
'AMT' => number_format( is_null( $amount ) ? $order->get_total() : $amount, 2, '.', '' ), |
41
|
|
|
'CURRENCYCODE' => $order->get_order_currency(), |
42
|
|
|
'COMPLETETYPE' => 'Complete', |
43
|
|
|
); |
44
|
|
|
return apply_filters( 'woocommerce_paypal_capture_request', $request, $order, $amount ); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Get refund request args. |
49
|
|
|
* @param WC_Order $order |
50
|
|
|
* @param float $amount |
51
|
|
|
* @param string $reason |
52
|
|
|
* @return array |
53
|
|
|
*/ |
54
|
|
|
public static function get_refund_request( $order, $amount = null, $reason = '' ) { |
55
|
|
|
$request = array( |
56
|
|
|
'VERSION' => '84.0', |
57
|
|
|
'SIGNATURE' => self::$api_signature, |
58
|
|
|
'USER' => self::$api_username, |
59
|
|
|
'PWD' => self::$api_password, |
60
|
|
|
'METHOD' => 'RefundTransaction', |
61
|
|
|
'TRANSACTIONID' => $order->get_transaction_id(), |
62
|
|
|
'NOTE' => html_entity_decode( wc_trim_string( $reason, 255 ), ENT_NOQUOTES, 'UTF-8' ), |
63
|
|
|
'REFUNDTYPE' => 'Full', |
64
|
|
|
); |
65
|
|
|
if ( ! is_null( $amount ) ) { |
66
|
|
|
$request['AMT'] = number_format( $amount, 2, '.', '' ); |
67
|
|
|
$request['CURRENCYCODE'] = $order->get_order_currency(); |
68
|
|
|
$request['REFUNDTYPE'] = 'Partial'; |
69
|
|
|
} |
70
|
|
|
return apply_filters( 'woocommerce_paypal_refund_request', $request, $order, $amount, $reason ); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Capture an authorization. |
75
|
|
|
* @param WC_Order $order |
76
|
|
|
* @param float $amount |
77
|
|
|
* @return object Either an object of name value pairs for a success, or a WP_ERROR object. |
78
|
|
|
*/ |
79
|
|
View Code Duplication |
public static function do_capture( $order, $amount = null ) { |
|
|
|
|
80
|
|
|
$raw_response = wp_safe_remote_post( |
81
|
|
|
self::$sandbox ? 'https://api-3t.sandbox.paypal.com/nvp' : 'https://api-3t.paypal.com/nvp', |
82
|
|
|
array( |
83
|
|
|
'method' => 'POST', |
84
|
|
|
'body' => self::get_capture_request( $order, $amount ), |
85
|
|
|
'timeout' => 70, |
86
|
|
|
'user-agent' => 'WooCommerce/' . WC()->version, |
87
|
|
|
'httpversion' => '1.1', |
88
|
|
|
) |
89
|
|
|
); |
90
|
|
|
|
91
|
|
|
WC_Gateway_Paypal::log( 'DoCapture Response: ' . print_r( $raw_response, true ) ); |
92
|
|
|
|
93
|
|
|
if ( empty( $raw_response['body'] ) ) { |
94
|
|
|
return new WP_Error( 'paypal-api', 'Empty Response' ); |
95
|
|
|
} elseif ( is_wp_error( $raw_response ) ) { |
96
|
|
|
return $raw_response; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
parse_str( $raw_response['body'], $response ); |
100
|
|
|
|
101
|
|
|
return (object) $response; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Refund an order via PayPal. |
106
|
|
|
* @param WC_Order $order |
107
|
|
|
* @param float $amount |
108
|
|
|
* @param string $reason |
109
|
|
|
* @return object Either an object of name value pairs for a success, or a WP_ERROR object. |
110
|
|
|
*/ |
111
|
|
View Code Duplication |
public static function refund_transaction( $order, $amount = null, $reason = '' ) { |
|
|
|
|
112
|
|
|
$raw_response = wp_safe_remote_post( |
113
|
|
|
self::$sandbox ? 'https://api-3t.sandbox.paypal.com/nvp' : 'https://api-3t.paypal.com/nvp', |
114
|
|
|
array( |
115
|
|
|
'method' => 'POST', |
116
|
|
|
'body' => self::get_refund_request( $order, $amount, $reason ), |
117
|
|
|
'timeout' => 70, |
118
|
|
|
'user-agent' => 'WooCommerce/' . WC()->version, |
119
|
|
|
'httpversion' => '1.1', |
120
|
|
|
) |
121
|
|
|
); |
122
|
|
|
|
123
|
|
|
WC_Gateway_Paypal::log( 'Refund Response: ' . print_r( $raw_response, true ) ); |
124
|
|
|
|
125
|
|
|
if ( empty( $raw_response['body'] ) ) { |
126
|
|
|
return new WP_Error( 'paypal-api', 'Empty Response' ); |
127
|
|
|
} elseif ( is_wp_error( $raw_response ) ) { |
128
|
|
|
return $raw_response; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
parse_str( $raw_response['body'], $response ); |
132
|
|
|
|
133
|
|
|
return (object) $response; |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Here for backwards compatibility. |
139
|
|
|
* @since 2.7.0 |
140
|
|
|
*/ |
141
|
|
|
class WC_Gateway_Paypal_Refund extends WC_Gateway_Paypal_API_Handler { |
142
|
|
|
public static function get_request( $order, $amount = null, $reason = '' ) { |
143
|
|
|
return self::get_refund_request( $order, $amount, $reason ); |
144
|
|
|
} |
145
|
|
|
public static function refund_order( $order, $amount = null, $reason = '', $sandbox = false ) { |
146
|
|
|
if ( $sandbox ) { |
147
|
|
|
self::$sandbox = $sandbox; |
148
|
|
|
} |
149
|
|
|
$result = self::refund_transaction( $order, $amount, $reason ); |
150
|
|
|
if ( is_wp_error( $result ) ) { |
151
|
|
|
return $result; |
152
|
|
|
} else { |
153
|
|
|
return (array) $result; |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.