blob: c681f176f07b71cc388f0f2db0d99604968b0686 [file] [log] [blame]
swissChilif0cbdc32023-01-05 17:21:38 -05001<?php
2if ( ! defined( 'ABSPATH' ) ) {
3 exit;
4}
5
6/**
7 * Abstract UPE Payment Method class
8 *
9 * Handles general functionality for UPE payment methods
10 */
11
12
13/**
14 * Extendable abstract class for payment methods.
15 */
16abstract class WC_Stripe_UPE_Payment_Method {
17
18 use WC_Stripe_Subscriptions_Utilities_Trait;
19 use WC_Stripe_Pre_Orders_Trait;
20
21 /**
22 * Stripe key name
23 *
24 * @var string
25 */
26 protected $stripe_id;
27
28 /**
29 * Display title
30 *
31 * @var string
32 */
33 protected $title;
34
35 /**
36 * Method label
37 *
38 * @var string
39 */
40 protected $label;
41
42 /**
43 * Method description
44 *
45 * @var string
46 */
47 protected $description;
48
49 /**
50 * Can payment method be saved or reused?
51 *
52 * @var bool
53 */
54 protected $is_reusable;
55
56 /**
57 * Array of currencies supported by this UPE method
58 *
59 * @var array
60 */
61 protected $supported_currencies;
62
63 /**
64 * Can this payment method be refunded?
65 *
66 * @var array
67 */
68 protected $can_refund = true;
69
70 /**
71 * Wether this UPE method is enabled
72 *
73 * @var bool
74 */
75 protected $enabled;
76
77 /**
78 * List of supported countries
79 *
80 * @var array
81 */
82 protected $supported_countries;
83
84 /**
85 * Create instance of payment method
86 */
87 public function __construct() {
88 $main_settings = get_option( 'woocommerce_stripe_settings' );
89
90 if ( isset( $main_settings['upe_checkout_experience_accepted_payments'] ) ) {
91 $enabled_upe_methods = $main_settings['upe_checkout_experience_accepted_payments'];
92 } else {
93 $enabled_upe_methods = [ WC_Stripe_UPE_Payment_Method_CC::STRIPE_ID ];
94 }
95
96 $this->enabled = in_array( static::STRIPE_ID, $enabled_upe_methods, true );
97 }
98
99 /**
100 * Returns payment method ID
101 *
102 * @return string
103 */
104 public function get_id() {
105 return $this->stripe_id;
106 }
107
108 /**
109 * Returns true if the UPE method is enabled.
110 *
111 * @return bool
112 */
113 public function is_enabled() {
114 return $this->enabled;
115 }
116
117 /**
118 * Returns true if the UPE method is available.
119 *
120 * @return bool
121 */
122 public function is_available() {
123 return true;
124 }
125
126 /**
127 * Returns payment method title
128 *
129 * @param array|bool $payment_details Optional payment details from charge object.
130 *
131 * @return string
132 */
133 public function get_title( $payment_details = false ) {
134 return $this->title;
135 }
136
137 /**
138 * Returns payment method label
139 *
140 * @return string
141 */
142 public function get_label() {
143 return $this->label;
144 }
145
146 /**
147 * Returns payment method description
148 *
149 * @return string
150 */
151 public function get_description() {
152 return $this->description;
153 }
154
155 /**
156 * Returns boolean dependent on whether payment method
157 * can be used at checkout
158 *
159 * @param int|null $order_id
160 * @return bool
161 */
162 public function is_enabled_at_checkout( $order_id = null ) {
163 // Check capabilities first.
164 if ( ! $this->is_capability_active() ) {
165 return false;
166 }
167
168 // Check currency compatibility.
169 $currencies = $this->get_supported_currencies();
170 if ( ! empty( $currencies ) && ! in_array( $this->get_woocommerce_currency(), $currencies, true ) ) {
171 return false;
172 }
173
174 // If cart or order contains subscription, enable payment method if it's reusable.
175 if ( $this->is_subscription_item_in_cart() || ( ! empty( $order_id ) && $this->has_subscription( $order_id ) ) ) {
176 return $this->is_reusable();
177 }
178
179 // If cart or order contains pre-order, enable payment method if it's reusable.
180 if ( $this->is_pre_order_item_in_cart() || ( ! empty( $order_id ) && $this->has_pre_order( $order_id ) ) ) {
181 return $this->is_reusable();
182 }
183
184 return true;
185 }
186
187 /**
188 * Validates if a payment method is available on a given country
189 *
190 * @param string $country a two-letter country code
191 *
192 * @return bool Will return true if supported_countries is empty on payment method
193 */
194 public function is_allowed_on_country( $country ) {
195 if ( ! empty( $this->supported_countries ) ) {
196 return in_array( $country, $this->supported_countries );
197 }
198
199 return true;
200 }
201
202 /**
203 * Returns boolean dependent on whether payment method
204 * will support saved payments/subscription payments
205 *
206 * @return bool
207 */
208 public function is_reusable() {
209 return $this->is_reusable;
210 }
211
212 /**
213 * Returns boolean dependent on whether capability
214 * for site account is enabled for payment method.
215 *
216 * @return bool
217 */
218 public function is_capability_active() {
219 // Treat all capabilities as active when in test mode.
220 $plugin_settings = get_option( 'woocommerce_stripe_settings' );
221 $test_mode_setting = ! empty( $plugin_settings['testmode'] ) ? $plugin_settings['testmode'] : 'no';
222
223 if ( 'yes' === $test_mode_setting ) {
224 return true;
225 }
226
227 // Otherwise, make sure the capability is available.
228 $capabilities = $this->get_capabilities_response();
229 if ( empty( $capabilities ) ) {
230 return false;
231 }
232 $key = $this->get_id() . '_payments';
233 return isset( $capabilities[ $key ] ) && 'active' === $capabilities[ $key ];
234 }
235
236 /**
237 * Returns capabilities response object for site account.
238 *
239 * @return object
240 */
241 public function get_capabilities_response() {
242 $account = WC_Stripe::get_instance()->account;
243 $data = $account->get_cached_account_data();
244 if ( empty( $data ) || ! isset( $data['capabilities'] ) ) {
245 return [];
246 }
247 return $data['capabilities'];
248 }
249
250 /**
251 * Returns string representing payment method type
252 * to query to retrieve saved payment methods from Stripe.
253 */
254 public function get_retrievable_type() {
255 return $this->is_reusable() ? WC_Stripe_UPE_Payment_Method_Sepa::STRIPE_ID : null;
256 }
257
258 /**
259 * Create new WC payment token and add to user.
260 *
261 * @param int $user_id WP_User ID
262 * @param object $payment_method Stripe payment method object
263 *
264 * @return WC_Payment_Token_SEPA
265 */
266 public function create_payment_token_for_user( $user_id, $payment_method ) {
267 $token = new WC_Payment_Token_SEPA();
268 $token->set_last4( $payment_method->sepa_debit->last4 );
269 $token->set_gateway_id( WC_Stripe_UPE_Payment_Gateway::ID );
270 $token->set_token( $payment_method->id );
271 $token->set_payment_method_type( $this->get_id() );
272 $token->set_user_id( $user_id );
273 $token->save();
274 return $token;
275 }
276
277 /**
278 * Returns the currencies this UPE method supports.
279 *
280 * @return array|null
281 */
282 public function get_supported_currencies() {
283 return apply_filters(
284 'wc_stripe_' . static::STRIPE_ID . '_upe_supported_currencies',
285 $this->supported_currencies
286 );
287 }
288
289 /**
290 * Wrapper function for get_woocommerce_currency global function
291 */
292 public function get_woocommerce_currency() {
293 return get_woocommerce_currency();
294 }
295
296 /**
297 * Returns whether the payment method requires automatic capture.
298 * By default all the UPE payment methods require automatic capture, except for "card".
299 *
300 * @return bool
301 */
302 public function requires_automatic_capture() {
303 return true;
304 }
305
306 /**
307 * Returns the HTML for the subtext messaging in the old settings UI.
308 *
309 * @param string $stripe_method_status (optional) Status of this payment method based on the Stripe's account capabilities
310 * @return string
311 */
312 public function get_subtext_messages( $stripe_method_status ) {
313 // can be either a `currency` or `activation` messaging, to be displayed in the old settings UI.
314 $messages = [];
315
316 if ( ! empty( $stripe_method_status ) && 'active' !== $stripe_method_status ) {
317 $text = __( 'Pending activation', 'woocommerce-gateway-stripe' );
318 $tooltip_content = sprintf(
319 /* translators: %1: Payment method name */
320 esc_attr__( '%1$s won\'t be visible to your customers until you provide the required information. Follow the instructions Stripe has sent to your e-mail address.', 'woocommerce-gateway-stripe' ),
321 $this->get_label()
322 );
323 $messages[] = $text . '<span class="tips" data-tip="' . $tooltip_content . '"><span class="woocommerce-help-tip" style="margin-top: 0;"></span></span>';
324 }
325
326 $currencies = $this->get_supported_currencies();
327 if ( ! empty( $currencies ) && ! in_array( get_woocommerce_currency(), $currencies, true ) ) {
328 /* translators: %s: List of comma-separated currencies. */
329 $tooltip_content = sprintf( esc_attr__( 'In order to be used at checkout, the payment method requires the store currency to be set to one of: %s', 'woocommerce-gateway-stripe' ), implode( ', ', $currencies ) );
330 $text = __( 'Requires currency', 'woocommerce-gateway-stripe' );
331
332 $messages[] = $text . '<span class="tips" data-tip="' . $tooltip_content . '"><span class="woocommerce-help-tip" style="margin-top: 0;"></span></span>';
333 }
334
335 return count( $messages ) > 0 ? join( '&nbsp;–&nbsp;', $messages ) : '';
336 }
337
338 /**
339 * Checks if payment method allows refund via stripe
340 *
341 * @return bool
342 */
343 public function can_refund_via_stripe() {
344 return $this->can_refund;
345 }
346}