PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 7.3.0-beta.1
WooCommerce v7.3.0-beta.1
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
518 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 * Constructor for the gateway.
40 */
41 public function __construct() {
42 $this->id = 'paypal';
43 $this->has_fields = false;
44 $this->order_button_text = __( 'Proceed to PayPal', 'woocommerce' );
45 $this->method_title = __( 'PayPal Standard', 'woocommerce' );
46 /* translators: %s: Link to WC system status page */
47 $this->method_description = __( 'PayPal Standard redirects customers to PayPal to enter their payment information.', 'woocommerce' );
48 $this->supports = array(
49 'products',
50 'refunds',
51 );
52
53 // Load the settings.
54 $this->init_form_fields();
55 $this->init_settings();
56
57 // Define user set variables.
58 $this->title = $this->get_option( 'title' );
59 $this->description = $this->get_option( 'description' );
60 $this->testmode = 'yes' === $this->get_option( 'testmode', 'no' );
61 $this->debug = 'yes' === $this->get_option( 'debug', 'no' );
62 $this->email = $this->get_option( 'email' );
63 $this->receiver_email = $this->get_option( 'receiver_email', $this->email );
64 $this->identity_token = $this->get_option( 'identity_token' );
65 self::$log_enabled = $this->debug;
66
67 if ( $this->testmode ) {
68 /* translators: %s: Link to PayPal sandbox testing guide page */
69 $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/' );
70 $this->description = trim( $this->description );
71 }
72
73 // Actions.
74 add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
75 add_action( 'woocommerce_order_status_processing', array( $this, 'capture_payment' ) );
76 add_action( 'woocommerce_order_status_completed', array( $this, 'capture_payment' ) );
77 add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
78
79 if ( ! $this->is_valid_for_use() ) {
80 $this->enabled = 'no';
81 } else {
82 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-ipn-handler.php';
83 new WC_Gateway_Paypal_IPN_Handler( $this->testmode, $this->receiver_email );
84
85 if ( $this->identity_token ) {
86 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-pdt-handler.php';
87 $pdt_handler = new WC_Gateway_Paypal_PDT_Handler( $this->testmode, $this->identity_token );
88 $pdt_handler->set_receiver_email( $this->receiver_email );
89 }
90 }
91
92 if ( 'yes' === $this->enabled ) {
93 add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'order_received_text' ), 10, 2 );
94 }
95 }
96
97 /**
98 * Return whether or not this gateway still requires setup to function.
99 *
100 * When this gateway is toggled on via AJAX, if this returns true a
101 * redirect will occur to the settings page instead.
102 *
103 * @since 3.4.0
104 * @return bool
105 */
106 public function needs_setup() {
107 return ! is_email( $this->email );
108 }
109
110 /**
111 * Logging method.
112 *
113 * @param string $message Log message.
114 * @param string $level Optional. Default 'info'. Possible values:
115 * emergency|alert|critical|error|warning|notice|info|debug.
116 */
117 public static function log( $message, $level = 'info' ) {
118 if ( self::$log_enabled ) {
119 if ( empty( self::$log ) ) {
120 self::$log = wc_get_logger();
121 }
122 self::$log->log( $level, $message, array( 'source' => 'paypal' ) );
123 }
124 }
125
126 /**
127 * Processes and saves options.
128 * If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out.
129 *
130 * @return bool was anything saved?
131 */
132 public function process_admin_options() {
133 $saved = parent::process_admin_options();
134
135 // Maybe clear logs.
136 if ( 'yes' !== $this->get_option( 'debug', 'no' ) ) {
137 if ( empty( self::$log ) ) {
138 self::$log = wc_get_logger();
139 }
140 self::$log->clear( 'paypal' );
141 }
142
143 return $saved;
144 }
145
146 /**
147 * Get gateway icon.
148 *
149 * @return string
150 */
151 public function get_icon() {
152 // We need a base country for the link to work, bail if in the unlikely event no country is set.
153 $base_country = WC()->countries->get_base_country();
154 if ( empty( $base_country ) ) {
155 return '';
156 }
157 $icon_html = '';
158 $icon = (array) $this->get_icon_image( $base_country );
159
160 foreach ( $icon as $i ) {
161 $icon_html .= '<img src="' . esc_attr( $i ) . '" alt="' . esc_attr__( 'PayPal acceptance mark', 'woocommerce' ) . '" />';
162 }
163
164 $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 ) ) );
165
166 return apply_filters( 'woocommerce_gateway_icon', $icon_html, $this->id );
167 }
168
169 /**
170 * Get the link for an icon based on country.
171 *
172 * @param string $country Country two letter code.
173 * @return string
174 */
175 protected function get_icon_url( $country ) {
176 $url = 'https://www.paypal.com/' . strtolower( $country );
177 $home_counties = array( 'BE', 'CZ', 'DK', 'HU', 'IT', 'JP', 'NL', 'NO', 'ES', 'SE', 'TR', 'IN' );
178 $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' );
179
180 if ( in_array( $country, $home_counties, true ) ) {
181 return $url . '/webapps/mpp/home';
182 } elseif ( in_array( $country, $countries, true ) ) {
183 return $url . '/webapps/mpp/paypal-popup';
184 } else {
185 return $url . '/cgi-bin/webscr?cmd=xpt/Marketing/general/WIPaypal-outside';
186 }
187 }
188
189 /**
190 * Get PayPal images for a country.
191 *
192 * @param string $country Country code.
193 * @return array of image URLs
194 */
195 protected function get_icon_image( $country ) {
196 switch ( $country ) {
197 case 'US':
198 case 'NZ':
199 case 'CZ':
200 case 'HU':
201 case 'MY':
202 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo/AM_mc_vs_dc_ae.jpg';
203 break;
204 case 'TR':
205 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_paypal_odeme_secenekleri.jpg';
206 break;
207 case 'GB':
208 $icon = 'https://www.paypalobjects.com/webstatic/mktg/Logo/AM_mc_vs_ms_ae_UK.png';
209 break;
210 case 'MX':
211 $icon = array(
212 'https://www.paypal.com/es_XC/Marketing/i/banner/paypal_visa_mastercard_amex.png',
213 'https://www.paypal.com/es_XC/Marketing/i/banner/paypal_debit_card_275x60.gif',
214 );
215 break;
216 case 'FR':
217 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_paypal_moyens_paiement_fr.jpg';
218 break;
219 case 'AU':
220 $icon = 'https://www.paypalobjects.com/webstatic/en_AU/mktg/logo/Solutions-graphics-1-184x80.jpg';
221 break;
222 case 'DK':
223 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_PayPal_betalingsmuligheder_dk.jpg';
224 break;
225 case 'RU':
226 $icon = 'https://www.paypalobjects.com/webstatic/ru_RU/mktg/business/pages/logo-center/AM_mc_vs_dc_ae.jpg';
227 break;
228 case 'NO':
229 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo-center/banner_pl_just_pp_319x110.jpg';
230 break;
231 case 'CA':
232 $icon = 'https://www.paypalobjects.com/webstatic/en_CA/mktg/logo-image/AM_mc_vs_dc_ae.jpg';
233 break;
234 case 'HK':
235 $icon = 'https://www.paypalobjects.com/webstatic/en_HK/mktg/logo/AM_mc_vs_dc_ae.jpg';
236 break;
237 case 'SG':
238 $icon = 'https://www.paypalobjects.com/webstatic/en_SG/mktg/Logos/AM_mc_vs_dc_ae.jpg';
239 break;
240 case 'TW':
241 $icon = 'https://www.paypalobjects.com/webstatic/en_TW/mktg/logos/AM_mc_vs_dc_ae.jpg';
242 break;
243 case 'TH':
244 $icon = 'https://www.paypalobjects.com/webstatic/en_TH/mktg/Logos/AM_mc_vs_dc_ae.jpg';
245 break;
246 case 'JP':
247 $icon = 'https://www.paypal.com/ja_JP/JP/i/bnr/horizontal_solution_4_jcb.gif';
248 break;
249 case 'IN':
250 $icon = 'https://www.paypalobjects.com/webstatic/mktg/logo/AM_mc_vs_dc_ae.jpg';
251 break;
252 default:
253 $icon = WC_HTTPS::force_https_url( WC()->plugin_url() . '/includes/gateways/paypal/assets/images/paypal.png' );
254 break;
255 }
256 return apply_filters( 'woocommerce_paypal_icon', $icon );
257 }
258
259 /**
260 * Check if this gateway is available in the user's country based on currency.
261 *
262 * @return bool
263 */
264 public function is_valid_for_use() {
265 return in_array(
266 get_woocommerce_currency(),
267 apply_filters(
268 'woocommerce_paypal_supported_currencies',
269 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' )
270 ),
271 true
272 );
273 }
274
275 /**
276 * Admin Panel Options.
277 * - Options for bits like 'title' and availability on a country-by-country basis.
278 *
279 * @since 1.0.0
280 */
281 public function admin_options() {
282 if ( $this->is_valid_for_use() ) {
283 parent::admin_options();
284 } else {
285 ?>
286 <div class="inline error">
287 <p>
288 <strong><?php esc_html_e( 'Gateway disabled', 'woocommerce' ); ?></strong>: <?php esc_html_e( 'PayPal Standard does not support your store currency.', 'woocommerce' ); ?>
289 </p>
290 </div>
291 <?php
292 }
293 }
294
295 /**
296 * Initialise Gateway Settings Form Fields.
297 */
298 public function init_form_fields() {
299 $this->form_fields = include __DIR__ . '/includes/settings-paypal.php';
300 }
301
302 /**
303 * Get the transaction URL.
304 *
305 * @param WC_Order $order Order object.
306 * @return string
307 */
308 public function get_transaction_url( $order ) {
309 if ( $this->testmode ) {
310 $this->view_transaction_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
311 } else {
312 $this->view_transaction_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
313 }
314 return parent::get_transaction_url( $order );
315 }
316
317 /**
318 * Process the payment and return the result.
319 *
320 * @param int $order_id Order ID.
321 * @return array
322 */
323 public function process_payment( $order_id ) {
324 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-request.php';
325
326 $order = wc_get_order( $order_id );
327 $paypal_request = new WC_Gateway_Paypal_Request( $this );
328
329 return array(
330 'result' => 'success',
331 'redirect' => $paypal_request->get_request_url( $order, $this->testmode ),
332 );
333 }
334
335 /**
336 * Can the order be refunded via PayPal?
337 *
338 * @param WC_Order $order Order object.
339 * @return bool
340 */
341 public function can_refund_order( $order ) {
342 $has_api_creds = false;
343
344 if ( $this->testmode ) {
345 $has_api_creds = $this->get_option( 'sandbox_api_username' ) && $this->get_option( 'sandbox_api_password' ) && $this->get_option( 'sandbox_api_signature' );
346 } else {
347 $has_api_creds = $this->get_option( 'api_username' ) && $this->get_option( 'api_password' ) && $this->get_option( 'api_signature' );
348 }
349
350 return $order && $order->get_transaction_id() && $has_api_creds;
351 }
352
353 /**
354 * Init the API class and set the username/password etc.
355 */
356 protected function init_api() {
357 include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-paypal-api-handler.php';
358
359 WC_Gateway_Paypal_API_Handler::$api_username = $this->testmode ? $this->get_option( 'sandbox_api_username' ) : $this->get_option( 'api_username' );
360 WC_Gateway_Paypal_API_Handler::$api_password = $this->testmode ? $this->get_option( 'sandbox_api_password' ) : $this->get_option( 'api_password' );
361 WC_Gateway_Paypal_API_Handler::$api_signature = $this->testmode ? $this->get_option( 'sandbox_api_signature' ) : $this->get_option( 'api_signature' );
362 WC_Gateway_Paypal_API_Handler::$sandbox = $this->testmode;
363 }
364
365 /**
366 * Process a refund if supported.
367 *
368 * @param int $order_id Order ID.
369 * @param float $amount Refund amount.
370 * @param string $reason Refund reason.
371 * @return bool|WP_Error
372 */
373 public function process_refund( $order_id, $amount = null, $reason = '' ) {
374 $order = wc_get_order( $order_id );
375
376 if ( ! $this->can_refund_order( $order ) ) {
377 return new WP_Error( 'error', __( 'Refund failed.', 'woocommerce' ) );
378 }
379
380 $this->init_api();
381
382 $result = WC_Gateway_Paypal_API_Handler::refund_transaction( $order, $amount, $reason );
383
384 if ( is_wp_error( $result ) ) {
385 $this->log( 'Refund Failed: ' . $result->get_error_message(), 'error' );
386 return new WP_Error( 'error', $result->get_error_message() );
387 }
388
389 $this->log( 'Refund Result: ' . wc_print_r( $result, true ) );
390
391 switch ( strtolower( $result->ACK ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
392 case 'success':
393 case 'successwithwarning':
394 $order->add_order_note(
395 /* translators: 1: Refund amount, 2: Refund ID */
396 sprintf( __( 'Refunded %1$s - Refund ID: %2$s', 'woocommerce' ), $result->GROSSREFUNDAMT, $result->REFUNDTRANSACTIONID ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
397 );
398 return true;
399 }
400
401 return isset( $result->L_LONGMESSAGE0 ) ? new WP_Error( 'error', $result->L_LONGMESSAGE0 ) : false; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
402 }
403
404 /**
405 * Capture payment when the order is changed from on-hold to complete or processing
406 *
407 * @param int $order_id Order ID.
408 */
409 public function capture_payment( $order_id ) {
410 $order = wc_get_order( $order_id );
411
412 if ( 'paypal' === $order->get_payment_method() && 'pending' === $order->get_meta( '_paypal_status', true ) && $order->get_transaction_id() ) {
413 $this->init_api();
414 $result = WC_Gateway_Paypal_API_Handler::do_capture( $order );
415
416 if ( is_wp_error( $result ) ) {
417 $this->log( 'Capture Failed: ' . $result->get_error_message(), 'error' );
418 /* translators: %s: Paypal gateway error message */
419 $order->add_order_note( sprintf( __( 'Payment could not be captured: %s', 'woocommerce' ), $result->get_error_message() ) );
420 return;
421 }
422
423 $this->log( 'Capture Result: ' . wc_print_r( $result, true ) );
424
425 // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
426 if ( ! empty( $result->PAYMENTSTATUS ) ) {
427 switch ( $result->PAYMENTSTATUS ) {
428 case 'Completed':
429 /* translators: 1: Amount, 2: Authorization ID, 3: Transaction ID */
430 $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 ) );
431 $order->update_meta_data( '_paypal_status', $result->PAYMENTSTATUS );
432 $order->set_transaction_id( $result->TRANSACTIONID );
433 $order->save();
434 break;
435 default:
436 /* translators: 1: Authorization ID, 2: Payment status */
437 $order->add_order_note( sprintf( __( 'Payment could not be captured - Auth ID: %1$s, Status: %2$s', 'woocommerce' ), $result->AUTHORIZATIONID, $result->PAYMENTSTATUS ) );
438 break;
439 }
440 }
441 // phpcs:enable
442 }
443 }
444
445 /**
446 * Load admin scripts.
447 *
448 * @since 3.3.0
449 */
450 public function admin_scripts() {
451 $screen = get_current_screen();
452 $screen_id = $screen ? $screen->id : '';
453
454 if ( 'woocommerce_page_wc-settings' !== $screen_id ) {
455 return;
456 }
457
458 $suffix = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
459 $version = Constants::get_constant( 'WC_VERSION' );
460
461 wp_enqueue_script( 'woocommerce_paypal_admin', WC()->plugin_url() . '/includes/gateways/paypal/assets/js/paypal-admin' . $suffix . '.js', array(), $version, true );
462 }
463
464 /**
465 * Custom PayPal order received text.
466 *
467 * @since 3.9.0
468 * @param string $text Default text.
469 * @param WC_Order $order Order data.
470 * @return string
471 */
472 public function order_received_text( $text, $order ) {
473 if ( $order && $this->id === $order->get_payment_method() ) {
474 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' );
475 }
476
477 return $text;
478 }
479
480 /**
481 * Determines whether PayPal Standard should be loaded or not.
482 *
483 * By default PayPal Standard isn't loaded on new installs or on existing sites which haven't set up the gateway.
484 *
485 * @since 5.5.0
486 *
487 * @return bool Whether PayPal Standard should be loaded.
488 */
489 public function should_load() {
490 $option_key = '_should_load';
491 $should_load = $this->get_option( $option_key );
492
493 if ( '' === $should_load ) {
494
495 // New installs without PayPal Standard enabled don't load it.
496 if ( 'no' === $this->enabled && WC_Install::is_new_install() ) {
497 $should_load = false;
498 } else {
499 $should_load = true;
500 }
501
502 $this->update_option( $option_key, wc_bool_to_string( $should_load ) );
503 } else {
504 $should_load = wc_string_to_bool( $should_load );
505 }
506
507 /**
508 * Allow third-parties to filter whether PayPal Standard should be loaded or not.
509 *
510 * @since 5.5.0
511 *
512 * @param bool $should_load Whether PayPal Standard should be loaded.
513 * @param WC_Gateway_Paypal $this The WC_Gateway_Paypal instance.
514 */
515 return apply_filters( 'woocommerce_should_load_paypal_standard', $should_load, $this );
516 }
517 }
518