PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 8.0.0-rc.2
WooCommerce v8.0.0-rc.2
10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / gateways / paypal / class-wc-gateway-paypal.php
woocommerce / includes / gateways / paypal Last commit date
assets 4 years ago includes 3 years ago class-wc-gateway-paypal.php 3 years ago
class-wc-gateway-paypal.php
554 lines
1 <?php
2 /**
3 * PayPal Standard Payment Gateway.
4 *
5 * Provides a PayPal Standard Payment Gateway.
6 *
7 * @class WC_Gateway_Paypal
8 * @extends WC_Payment_Gateway
9 * @version 2.3.0
10 * @package WooCommerce\Classes\Payment
11 */
12
13 use Automattic\Jetpack\Constants;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * WC_Gateway_Paypal Class.
21 */
22 class WC_Gateway_Paypal extends WC_Payment_Gateway {
23
24 /**
25 * Whether or not logging is enabled
26 *
27 * @var bool
28 */
29 public static $log_enabled = false;
30
31 /**
32 * Logger instance
33 *
34 * @var WC_Logger
35 */
36 public static $log = false;
37
38 /**
39 * Whether the test mode is enabled.
40 *
41 * @var bool
42 */
43 public $testmode;
44
45 /**
46 * Whether the debug mode is enabled.
47 *
48 * @var bool
49 */
50 public $debug;
51
52 /**
53 * Email address to send payments to.
54 *
55 * @var string
56 */
57 public $email;
58
59 /**
60 * Receiver email.
61 *
62 * @var string
63 */
64 public $receiver_email;
65
66 /**
67 * Identity token.
68 *
69 * @var string
70 */
71 public $identity_token;
72
73
74 /**
75 * Constructor for the gateway.
76 */
77 public function __construct() {
78 $this->id = 'paypal';
79 $this->has_fields = false;
80 $this->order_button_text = __( 'Proceed to PayPal', 'woocommerce' );
81 $this->method_title = __( 'PayPal Standard', 'woocommerce' );
82 /* translators: %s: Link to WC system status page */
83 $this->method_description = __( 'PayPal Standard redirects customers to PayPal to enter their payment information.', 'woocommerce' );
84 $this->supports = array(
85 'products',
86 'refunds',
87 );
88
89 // Load the settings.
90 $this->init_form_fields();
91 $this->init_settings();
92
93 // Define user set variables.
94 $this->title = $this->get_option( 'title' );
95 $this->description = $this->get_option( 'description' );
96 $this->testmode = 'yes' === $this->get_option( 'testmode', 'no' );
97 $this->debug = 'yes' === $this->get_option( 'debug', 'no' );
98 $this->email = $this->get_option( 'email' );
99 $this->receiver_email = $this->get_option( 'receiver_email', $this->email );
100 $this->identity_token = $this->get_option( 'identity_token' );
101 self::$log_enabled = $this->debug;
102
103 if ( $this->testmode ) {
104 /* translators: %s: Link to PayPal sandbox testing guide page */
105 $this->description .= ' ' . sprintf( __( 'SANDBOX ENABLED. You can use sandbox testing accounts only. See the <a href="%s">PayPal Sandbox Testing Guide</a> for more details.', 'woocommerce' ), 'https://developer.paypal.com/docs/classic/lifecycle/ug_sandbox/' );
106 $this->description = trim( $this->description );
107 }
108
109 // Actions.
110 add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
111 add_action( 'woocommerce_order_status_processing', array( $this, 'capture_payment' ) );
112 add_action( 'woocommerce_order_status_completed', array( $this, 'capture_payment' ) );
113 add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
114
115 if ( ! $this->is_valid_for_use() ) {
116 $this->enabled = 'no';
117 } else {
118 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-ipn-handler.php';
119 new WC_Gateway_Paypal_IPN_Handler( $this->testmode, $this->receiver_email );
120
121 if ( $this->identity_token ) {
122 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-pdt-handler.php';
123 $pdt_handler = new WC_Gateway_Paypal_PDT_Handler( $this->testmode, $this->identity_token );
124 $pdt_handler->set_receiver_email( $this->receiver_email );
125 }
126 }
127
128 if ( 'yes' === $this->enabled ) {
129 add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'order_received_text' ), 10, 2 );
130 }
131 }
132
133 /**
134 * Return whether or not this gateway still requires setup to function.
135 *
136 * When this gateway is toggled on via AJAX, if this returns true a
137 * redirect will occur to the settings page instead.
138 *
139 * @since 3.4.0
140 * @return bool
141 */
142 public function needs_setup() {
143 return ! is_email( $this->email );
144 }
145
146 /**
147 * Logging method.
148 *
149 * @param string $message Log message.
150 * @param string $level Optional. Default 'info'. Possible values:
151 * emergency|alert|critical|error|warning|notice|info|debug.
152 */
153 public static function log( $message, $level = 'info' ) {
154 if ( self::$log_enabled ) {
155 if ( empty( self::$log ) ) {
156 self::$log = wc_get_logger();
157 }
158 self::$log->log( $level, $message, array( 'source' => 'paypal' ) );
159 }
160 }
161
162 /**
163 * Processes and saves options.
164 * If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out.
165 *
166 * @return bool was anything saved?
167 */
168 public function process_admin_options() {
169 $saved = parent::process_admin_options();
170
171 // Maybe clear logs.
172 if ( 'yes' !== $this->get_option( 'debug', 'no' ) ) {
173 if ( empty( self::$log ) ) {
174 self::$log = wc_get_logger();
175 }
176 self::$log->clear( 'paypal' );
177 }
178
179 return $saved;
180 }
181
182 /**
183 * Get gateway icon.
184 *
185 * @return string
186 */
187 public function get_icon() {
188 // We need a base country for the link to work, bail if in the unlikely event no country is set.
189 $base_country = WC()->countries->get_base_country();
190 if ( empty( $base_country ) ) {
191 return '';
192 }
193 $icon_html = '';
194 $icon = (array) $this->get_icon_image( $base_country );
195
196 foreach ( $icon as $i ) {
197 $icon_html .= '<img src="' . esc_attr( $i ) . '" alt="' . esc_attr__( 'PayPal acceptance mark', 'woocommerce' ) . '" />';
198 }
199
200 $icon_html .= sprintf( '<a href="%1$s" class="about_paypal" onclick="javascript:window.open(\'%1$s\',\'WIPaypal\',\'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=1060, height=700\'); return false;">' . esc_attr__( 'What is PayPal?', 'woocommerce' ) . '</a>', esc_url( $this->get_icon_url( $base_country ) ) );
201
202 return apply_filters( 'woocommerce_gateway_icon', $icon_html, $this->id );
203 }
204
205 /**
206 * Get the link for an icon based on country.
207 *
208 * @param string $country Country two letter code.
209 * @return string
210 */
211 protected function get_icon_url( $country ) {
212 $url = 'https://www.paypal.com/' . strtolower( $country );
213 $home_counties = array( 'BE', 'CZ', 'DK', 'HU', 'IT', 'JP', 'NL', 'NO', 'ES', 'SE', 'TR', 'IN' );
214 $countries = array( 'DZ', 'AU', 'BH', 'BQ', 'BW', 'CA', 'CN', 'CW', 'FI', 'FR', 'DE', 'GR', 'HK', 'ID', 'JO', 'KE', 'KW', 'LU', 'MY', 'MA', 'OM', 'PH', 'PL', 'PT', 'QA', 'IE', 'RU', 'BL', 'SX', 'MF', 'SA', 'SG', 'SK', 'KR', 'SS', 'TW', 'TH', 'AE', 'GB', 'US', 'VN' );
215
216 if ( in_array( $country, $home_counties, true ) ) {
217 return $url . '/webapps/mpp/home';
218 } elseif ( in_array( $country, $countries, true ) ) {
219 return $url . '/webapps/mpp/paypal-popup';
220 } else {
221 return $url . '/cgi-bin/webscr?cmd=xpt/Marketing/general/WIPaypal-outside';
222 }
223 }
224
225 /**
226 * Get PayPal images for a country.
227 *
228 * @param string $country Country code.
229 * @return array of image URLs
230 */
231 protected function get_icon_image( $country ) {
232 switch ( $country ) {
233 case 'US':
234 case 'NZ':
235 case 'CZ':
236 case 'HU':
237 case 'MY':
238 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo/AM_mc_vs_dc_ae.jpg';
239 break;
240 case 'TR':
241 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_paypal_odeme_secenekleri.jpg';
242 break;
243 case 'GB':
244 $icon = 'https://www.paypalobjects.com/webstatic/mktg/Logo/AM_mc_vs_ms_ae_UK.png';
245 break;
246 case 'MX':
247 $icon = array(
248 'https://www.paypal.com/es_XC/Marketing/i/banner/paypal_visa_mastercard_amex.png',
249 'https://www.paypal.com/es_XC/Marketing/i/banner/paypal_debit_card_275x60.gif',
250 );
251 break;
252 case 'FR':
253 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_paypal_moyens_paiement_fr.jpg';
254 break;
255 case 'AU':
256 $icon = 'https://www.paypalobjects.com/webstatic/en_AU/mktg/logo/Solutions-graphics-1-184x80.jpg';
257 break;
258 case 'DK':
259 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_PayPal_betalingsmuligheder_dk.jpg';
260 break;
261 case 'RU':
262 $icon = 'https://www.paypalobjects.com/webstatic/ru_RU/mktg/business/pages/logo-center/AM_mc_vs_dc_ae.jpg';
263 break;
264 case 'NO':
265 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/banner_pl_just_pp_319x110.jpg';
266 break;
267 case 'CA':
268 $icon = 'https://www.paypalobjects.com/webstatic/en_CA/mktg/logo-image/AM_mc_vs_dc_ae.jpg';
269 break;
270 case 'HK':
271 $icon = 'https://www.paypalobjects.com/webstatic/en_HK/mktg/logo/AM_mc_vs_dc_ae.jpg';
272 break;
273 case 'SG':
274 $icon = 'https://www.paypalobjects.com/webstatic/en_SG/mktg/Logos/AM_mc_vs_dc_ae.jpg';
275 break;
276 case 'TW':
277 $icon = 'https://www.paypalobjects.com/webstatic/en_TW/mktg/logos/AM_mc_vs_dc_ae.jpg';
278 break;
279 case 'TH':
280 $icon = 'https://www.paypalobjects.com/webstatic/en_TH/mktg/Logos/AM_mc_vs_dc_ae.jpg';
281 break;
282 case 'JP':
283 $icon = 'https://www.paypal.com/ja_JP/JP/i/bnr/horizontal_solution_4_jcb.gif';
284 break;
285 case 'IN':
286 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo/AM_mc_vs_dc_ae.jpg';
287 break;
288 default:
289 $icon = WC_HTTPS::force_https_url( WC()->plugin_url() . '/includes/gateways/paypal/assets/images/paypal.png' );
290 break;
291 }
292 return apply_filters( 'woocommerce_paypal_icon', $icon );
293 }
294
295 /**
296 * Check if this gateway is available in the user's country based on currency.
297 *
298 * @return bool
299 */
300 public function is_valid_for_use() {
301 return in_array(
302 get_woocommerce_currency(),
303 apply_filters(
304 'woocommerce_paypal_supported_currencies',
305 array( 'AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP', 'RMB', 'RUB', 'INR' )
306 ),
307 true
308 );
309 }
310
311 /**
312 * Admin Panel Options.
313 * - Options for bits like 'title' and availability on a country-by-country basis.
314 *
315 * @since 1.0.0
316 */
317 public function admin_options() {
318 if ( $this->is_valid_for_use() ) {
319 parent::admin_options();
320 } else {
321 ?>
322 <div class="inline error">
323 <p>
324 <strong><?php esc_html_e( 'Gateway disabled', 'woocommerce' ); ?></strong>: <?php esc_html_e( 'PayPal Standard does not support your store currency.', 'woocommerce' ); ?>
325 </p>
326 </div>
327 <?php
328 }
329 }
330
331 /**
332 * Initialise Gateway Settings Form Fields.
333 */
334 public function init_form_fields() {
335 $this->form_fields = include __DIR__ . '/includes/settings-paypal.php';
336 }
337
338 /**
339 * Get the transaction URL.
340 *
341 * @param WC_Order $order Order object.
342 * @return string
343 */
344 public function get_transaction_url( $order ) {
345 if ( $this->testmode ) {
346 $this->view_transaction_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
347 } else {
348 $this->view_transaction_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
349 }
350 return parent::get_transaction_url( $order );
351 }
352
353 /**
354 * Process the payment and return the result.
355 *
356 * @param int $order_id Order ID.
357 * @return array
358 */
359 public function process_payment( $order_id ) {
360 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-request.php';
361
362 $order = wc_get_order( $order_id );
363 $paypal_request = new WC_Gateway_Paypal_Request( $this );
364
365 return array(
366 'result' => 'success',
367 'redirect' => $paypal_request->get_request_url( $order, $this->testmode ),
368 );
369 }
370
371 /**
372 * Can the order be refunded via PayPal?
373 *
374 * @param WC_Order $order Order object.
375 * @return bool
376 */
377 public function can_refund_order( $order ) {
378 $has_api_creds = false;
379
380 if ( $this->testmode ) {
381 $has_api_creds = $this->get_option( 'sandbox_api_username' ) && $this->get_option( 'sandbox_api_password' ) && $this->get_option( 'sandbox_api_signature' );
382 } else {
383 $has_api_creds = $this->get_option( 'api_username' ) && $this->get_option( 'api_password' ) && $this->get_option( 'api_signature' );
384 }
385
386 return $order && $order->get_transaction_id() && $has_api_creds;
387 }
388
389 /**
390 * Init the API class and set the username/password etc.
391 */
392 protected function init_api() {
393 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-api-handler.php';
394
395 WC_Gateway_Paypal_API_Handler::$api_username = $this->testmode ? $this->get_option( 'sandbox_api_username' ) : $this->get_option( 'api_username' );
396 WC_Gateway_Paypal_API_Handler::$api_password = $this->testmode ? $this->get_option( 'sandbox_api_password' ) : $this->get_option( 'api_password' );
397 WC_Gateway_Paypal_API_Handler::$api_signature = $this->testmode ? $this->get_option( 'sandbox_api_signature' ) : $this->get_option( 'api_signature' );
398 WC_Gateway_Paypal_API_Handler::$sandbox = $this->testmode;
399 }
400
401 /**
402 * Process a refund if supported.
403 *
404 * @param int $order_id Order ID.
405 * @param float $amount Refund amount.
406 * @param string $reason Refund reason.
407 * @return bool|WP_Error
408 */
409 public function process_refund( $order_id, $amount = null, $reason = '' ) {
410 $order = wc_get_order( $order_id );
411
412 if ( ! $this->can_refund_order( $order ) ) {
413 return new WP_Error( 'error', __( 'Refund failed.', 'woocommerce' ) );
414 }
415
416 $this->init_api();
417
418 $result = WC_Gateway_Paypal_API_Handler::refund_transaction( $order, $amount, $reason );
419
420 if ( is_wp_error( $result ) ) {
421 $this->log( 'Refund Failed: ' . $result->get_error_message(), 'error' );
422 return new WP_Error( 'error', $result->get_error_message() );
423 }
424
425 $this->log( 'Refund Result: ' . wc_print_r( $result, true ) );
426
427 switch ( strtolower( $result->ACK ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
428 case 'success':
429 case 'successwithwarning':
430 $order->add_order_note(
431 /* translators: 1: Refund amount, 2: Refund ID */
432 sprintf( __( 'Refunded %1$s - Refund ID: %2$s', 'woocommerce' ), $result->GROSSREFUNDAMT, $result->REFUNDTRANSACTIONID ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
433 );
434 return true;
435 }
436
437 return isset( $result->L_LONGMESSAGE0 ) ? new WP_Error( 'error', $result->L_LONGMESSAGE0 ) : false; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
438 }
439
440 /**
441 * Capture payment when the order is changed from on-hold to complete or processing
442 *
443 * @param int $order_id Order ID.
444 */
445 public function capture_payment( $order_id ) {
446 $order = wc_get_order( $order_id );
447
448 if ( 'paypal' === $order->get_payment_method() && 'pending' === $order->get_meta( '_paypal_status', true ) && $order->get_transaction_id() ) {
449 $this->init_api();
450 $result = WC_Gateway_Paypal_API_Handler::do_capture( $order );
451
452 if ( is_wp_error( $result ) ) {
453 $this->log( 'Capture Failed: ' . $result->get_error_message(), 'error' );
454 /* translators: %s: Paypal gateway error message */
455 $order->add_order_note( sprintf( __( 'Payment could not be captured: %s', 'woocommerce' ), $result->get_error_message() ) );
456 return;
457 }
458
459 $this->log( 'Capture Result: ' . wc_print_r( $result, true ) );
460
461 // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
462 if ( ! empty( $result->PAYMENTSTATUS ) ) {
463 switch ( $result->PAYMENTSTATUS ) {
464 case 'Completed':
465 /* translators: 1: Amount, 2: Authorization ID, 3: Transaction ID */
466 $order->add_order_note( sprintf( __( 'Payment of %1$s was captured - Auth ID: %2$s, Transaction ID: %3$s', 'woocommerce' ), $result->AMT, $result->AUTHORIZATIONID, $result->TRANSACTIONID ) );
467 $order->update_meta_data( '_paypal_status', $result->PAYMENTSTATUS );
468 $order->set_transaction_id( $result->TRANSACTIONID );
469 $order->save();
470 break;
471 default:
472 /* translators: 1: Authorization ID, 2: Payment status */
473 $order->add_order_note( sprintf( __( 'Payment could not be captured - Auth ID: %1$s, Status: %2$s', 'woocommerce' ), $result->AUTHORIZATIONID, $result->PAYMENTSTATUS ) );
474 break;
475 }
476 }
477 // phpcs:enable
478 }
479 }
480
481 /**
482 * Load admin scripts.
483 *
484 * @since 3.3.0
485 */
486 public function admin_scripts() {
487 $screen = get_current_screen();
488 $screen_id = $screen ? $screen->id : '';
489
490 if ( 'woocommerce_page_wc-settings' !== $screen_id ) {
491 return;
492 }
493
494 $suffix = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
495 $version = Constants::get_constant( 'WC_VERSION' );
496
497 wp_enqueue_script( 'woocommerce_paypal_admin', WC()->plugin_url() . '/includes/gateways/paypal/assets/js/paypal-admin' . $suffix . '.js', array(), $version, true );
498 }
499
500 /**
501 * Custom PayPal order received text.
502 *
503 * @since 3.9.0
504 * @param string $text Default text.
505 * @param WC_Order $order Order data.
506 * @return string
507 */
508 public function order_received_text( $text, $order ) {
509 if ( $order && $this->id === $order->get_payment_method() ) {
510 return esc_html__( 'Thank you for your payment. Your transaction has been completed, and a receipt for your purchase has been emailed to you. Log into your PayPal account to view transaction details.', 'woocommerce' );
511 }
512
513 return $text;
514 }
515
516 /**
517 * Determines whether PayPal Standard should be loaded or not.
518 *
519 * By default PayPal Standard isn't loaded on new installs or on existing sites which haven't set up the gateway.
520 *
521 * @since 5.5.0
522 *
523 * @return bool Whether PayPal Standard should be loaded.
524 */
525 public function should_load() {
526 $option_key = '_should_load';
527 $should_load = $this->get_option( $option_key );
528
529 if ( '' === $should_load ) {
530
531 // New installs without PayPal Standard enabled don't load it.
532 if ( 'no' === $this->enabled && WC_Install::is_new_install() ) {
533 $should_load = false;
534 } else {
535 $should_load = true;
536 }
537
538 $this->update_option( $option_key, wc_bool_to_string( $should_load ) );
539 } else {
540 $should_load = wc_string_to_bool( $should_load );
541 }
542
543 /**
544 * Allow third-parties to filter whether PayPal Standard should be loaded or not.
545 *
546 * @since 5.5.0
547 *
548 * @param bool $should_load Whether PayPal Standard should be loaded.
549 * @param WC_Gateway_Paypal $this The WC_Gateway_Paypal instance.
550 */
551 return apply_filters( 'woocommerce_should_load_paypal_standard', $should_load, $this );
552 }
553 }
554