PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.9
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.9
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / gateways / class-charitable-gateway-stripe-am.php

class-charitable-gateway-stripe-am.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0.9, at includes/gateways/class-charitable-gateway-stripe-am.php

1,442 lines 47.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Stripe Payment Gateway class.
4 *
5 * @package Charitable/Classes/Charitable_Gateway_Stripe_AM
6 * @author David Bisset
7 * @copyright Copyright (c) 2022, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.0.0
10 * @version 1.6.55
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Gateway_Stripe_AM' ) ) :
19
20 /**
21 * Stripe Gateway.
22 *
23 * @since 1.0.0
24 */
25 class Charitable_Gateway_Stripe_AM extends Charitable_Gateway {
26
27 /** The gateway ID. */
28 const ID = 'stripe';
29
30 /** The Stripe API version we are using. */
31 const STRIPE_API_VERSION = '2019-03-14';
32
33 /**
34 * Gateway badge.
35 */
36 var $badge = '';
37
38 /**
39 * Instantiate the gateway class, defining its key values.
40 *
41 * @since 1.0.0
42 */
43 public function __construct() {
44
45 /**
46 * Filter the gateway name
47 *
48 * @since 1.0.0
49 *
50 * @param string $name Gateway name.
51 */
52 $this->name = apply_filters( 'charitable_gateway_stripe_name', __( 'Stripe', 'charitable-stripe' ) );
53
54 $this->defaults = [
55 'label' => __( 'Stripe', 'charitable-stripe' ),
56 ];
57
58 $this->badge = __( 'Preferred!', 'charitable' );
59
60 $this->supports = [
61 '1.3.0',
62 'credit-card',
63 'recurring',
64 'refunds',
65 ];
66
67 /* Needed for backwards compatibility with Charitable < 1.3 */
68 $this->credit_card_form = true;
69
70 add_filter( 'charitable_option_enable_stripe_checkout', array( $this, 'maybe_return_stripe_connect_setting'), 10, 4 );
71 add_filter( 'charitable_option_enable_checkout_billing_address_collection', array( $this, 'maybe_return_stripe_connect_setting'), 10, 4 );
72 add_filter( 'charitable_option_statement_descriptor', array( $this, 'maybe_return_stripe_connect_setting'), 10, 4 );
73 add_filter( 'charitable_option_statement_descriptor_custom', array( $this, 'maybe_return_stripe_connect_setting'), 10, 4 );
74
75 add_action( 'charitable_stripe_ipn_event', array( $this, 'maybe_process_webhook_with_stripe_connect'), 10, 2 );
76
77 add_filter( 'charitable_minimum_donation_amount', array( $this, 'set_minimum_donation_amount'), 10 );
78
79 }
80
81 /**
82 * Register the Stripe payment gateway class.
83 *
84 * @param string[] $gateways The list of registered gateways.
85 * @return string[]
86 * @since 1.7.0
87 */
88 public static function register_gateway( $gateways ) {
89 $gateways['stripe'] = 'Charitable_Gateway_Stripe';
90 return $gateways;
91 }
92
93 /**
94 * Register gateway settings.
95 *
96 * @param array $settings The existing settings to display for the Stripe settings page.
97 * @return array
98 * @since 1.7.0
99 */
100 public function gateway_settings( $settings ) {
101
102 if ( ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) || charitable_is_admin_debug() ) {
103
104 if ( charitable()->is_stripe_connect_addon() ) {
105
106 $settings = $settings + array( 'enable_stripe_checkout' => [
107 'type' => 'checkbox',
108 'title' => __( 'Use Stripe Checkout', 'charitable-stripe' ),
109 'priority' => 4,
110 'help' => __( 'When you enable Stripe Checkout, donors enter their credit card details into a secure hosted payment page managed by Stripe. <a href="https://stripe.com/docs/checkout" target="_blank">https://stripe.com/docs/checkout</a>', 'charitable-stripe' ),
111 ]);
112
113 }
114
115 return array_merge( $settings, array(
116 'section_live_mode' => [
117 'title' => __( 'Live Settings', 'charitable-stripe' ),
118 'type' => 'heading',
119 'priority' => 5,
120 ],
121 'live_secret_key' => [
122 'type' => 'text',
123 'title' => __( 'Live Secret Key', 'charitable-stripe' ),
124 'priority' => 6,
125 'class' => 'wide',
126 ],
127 'live_public_key' => [
128 'type' => 'text',
129 'title' => __( 'Live Publishable Key', 'charitable-stripe' ),
130 'priority' => 7,
131 'class' => 'wide',
132 ],
133 'section_test_mode' => [
134 'title' => __( 'Test Settings', 'charitable-stripe' ),
135 'type' => 'heading',
136 'priority' => 10,
137 ],
138 'test_secret_key' => [
139 'type' => 'text',
140 'title' => __( 'Test Secret Key', 'charitable-stripe' ),
141 'priority' => 11,
142 'class' => 'wide',
143 ],
144 'test_public_key' => [
145 'type' => 'text',
146 'title' => __( 'Test Publishable Key', 'charitable-stripe' ),
147 'priority' => 12,
148 'class' => 'wide',
149 ],
150 'api_description' => array(
151 'type' => 'content',
152 'title' => __( 'Connection Status', 'charitable' ),
153 'content' => $this->get_connection_status_content(),
154 'priority' => 21,
155 ),
156 ) );
157
158
159 } else {
160
161 $stripe_settings = array(
162 'api_description' => array(
163 'type' => 'content',
164 'title' => __( 'Connection Status', 'charitable' ),
165 'content' => $this->get_connection_status_content(),
166 'priority' => 5,
167 )
168 );
169
170 if ( charitable_get_option( 'test_mode' ) || ( isset( $force_test_mode ) && $force_test_mode ) ) {
171 $mode = 'test';
172 } else {
173 $mode = 'live';
174 }
175
176
177 if ( $this->check_keys_exist( $mode ) && false === charitable_using_stripe_connect() && charitable()->is_stripe_connect_addon() ) {
178 // if there ARE keys and the Stripe addon is active... BUT WE ARE NOT USING 1.70 Stripe Connect... so this is most likely previous stripe addon keys
179 $stripe_settings = $stripe_settings + array( 'stripe_modify_keys' => [
180 'title' => __( ' ', 'charitable-stripe' ),
181 'type' => 'content',
182 'class' => 'manually-modify',
183 'content' => '<a href="#" data-charitable-args="mode=' . $mode . '" data-charitable-action="show-stripe-keys" class="manually-modify-keys" id="charitable-modify-keys">Manually Modify Keys</a>',
184 'priority' => 15,
185 ] );
186 }
187
188 if ( charitable()->is_stripe_connect_addon() ) {
189
190 $stripe_settings = $stripe_settings + array( 'enable_stripe_checkout' => [
191 'type' => 'checkbox',
192 'title' => __( 'Use Stripe Checkout', 'charitable-stripe' ),
193 'priority' => 16,
194 'help' => __( 'When you enable Stripe Checkout, donors enter their credit card details into a secure hosted payment page managed by Stripe. <a href="https://stripe.com/docs/checkout" target="_blank">https://stripe.com/docs/checkout</a>', 'charitable-stripe' ),
195 ],
196 'enable_checkout_billing_address_collection' => [
197 'type' => 'checkbox',
198 'title' => __( 'Require Billing Address in Checkout', 'charitable-stripe' ),
199 'priority' => 17,
200 'help' => __( 'If enabled, donors will always be asked to enter their billing address in Checkout.', 'charitable-stripe' ),
201 'attrs' => [
202 'data-trigger-key' => '#charitable_settings_gateways_stripe_enable_stripe_checkout',
203 'data-trigger-value' => 'checked',
204 ],
205 ],
206 'section_statement_descriptor' => [
207 'type' => 'heading',
208 'title' => __( 'Statement Descriptor' ),
209 'priority' => 20,
210 ],
211 'statement_descriptor' => [
212 'type' => 'select',
213 'title' => __( 'Format', 'charitable-stripe' ),
214 'priority' => 21,
215 'help' => __( 'Customize the statement descriptor that will appear on donors\' bank statements.', 'charitable-stripe' ),
216 'default' => 'auto',
217 'options' => [
218 'auto' => __( 'Use campaign title', 'charitable-stripe' ),
219 'custom' => __( 'Set a custom descriptor', 'charitable-stipe' ),
220 ],
221 ],
222 'statement_descriptor_custom' => [
223 'type' => 'text',
224 'title' => __( 'Custom Statement Descriptor', 'charitable-stripe' ),
225 'priority' => 22,
226 'help' => __( 'A custom statement descriptor up to 22 characters long.', 'charitable-stripe' ),
227 'attrs' => [
228 'data-trigger-key' => '#charitable_settings_gateways_stripe_statement_descriptor',
229 'data-trigger-value' => 'custom',
230 'maxlength' => 22,
231 ],
232 ] );
233 }
234
235 if ( charitable_using_stripe_connect() ) {
236
237 unset( $stripe_settings['section_live_mode'] );
238 unset( $stripe_settings['live_secret_key'] );
239 unset( $stripe_settings['live_public_key'] );
240 unset( $stripe_settings['section_test_mode'] );
241 unset( $stripe_settings['test_secret_key'] );
242 unset( $stripe_settings['test_public_key'] );
243
244 }
245
246 if ( ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) || charitable_is_admin_debug() ) {
247 $stripe_settings = $stripe_settings + array( 'section_stripe_checkout' => [
248 'title' => __( 'Stripe Checkout INTERNAL', 'charitable-stripe' ),
249 'type' => 'heading',
250 'priority' => 4,
251 ],
252 'section_live_mode' => [
253 'title' => __( 'Live Settings', 'charitable-stripe' ),
254 'type' => 'heading',
255 'priority' => 5,
256 ],
257 'live_secret_key' => [
258 'type' => 'text',
259 'title' => __( 'Live Secret Key', 'charitable-stripe' ),
260 'priority' => 6,
261 'class' => 'wide',
262 ],
263 'live_public_key' => [
264 'type' => 'text',
265 'title' => __( 'Live Publishable Key', 'charitable-stripe' ),
266 'priority' => 7,
267 'class' => 'wide',
268 ],
269 'section_test_mode' => [
270 'title' => __( 'Test Settings', 'charitable-stripe' ),
271 'type' => 'heading',
272 'priority' => 10,
273 ],
274 'test_secret_key' => [
275 'type' => 'text',
276 'title' => __( 'Test Secret Key', 'charitable-stripe' ),
277 'priority' => 11,
278 'class' => 'wide',
279 ],
280 'test_public_key' => [
281 'type' => 'text',
282 'title' => __( 'Test Publishable Key', 'charitable-stripe' ),
283 'priority' => 12,
284 'class' => 'wide',
285 ] );
286 }
287
288 return array_merge( $settings, $stripe_settings );
289
290 }
291
292 }
293
294 public function get_connection_status_content( $force_test_mode = false ) {
295
296 if ( charitable_get_option( 'test_mode' ) || $force_test_mode ) {
297 $mode = 'test';
298 } else {
299 $mode = 'live';
300 }
301
302 $html = '';
303
304 if ( ! $this->check_keys_exist( $mode ) || ! charitable_using_stripe_connect() ) {
305 $html .= $this->get_stripe_connect_button();
306 } else {
307 $html .= '<p id="wpcharitable-stripe-auth-error-account-actions" style="display: block;">' . sprintf(
308 /* translators: %1$s Stripe payment mode. %2$s Opening anchor tag for reconnecting to Stripe, do not translate. %3$s Opening anchor tag for disconnecting Stripe, do not translate. %4$s Closing anchor tag, do not translate. */
309 __( '%1$sDisconnect this account%2$s.', 'stripe' ),
310 '<strong>Connected In ' . $mode . ' mode</strong>. <a href="' . esc_url( $this->get_stripe_disconnect_url() ) . '" class="wpcharitable-disconnect-link">',
311 '</a>'
312 ) . '</p>';
313
314 $html .= '<p id="wpcharitable-stripe-activated-account-actions" style="display: none;">' . sprintf(
315 /* translators: %1$s Stripe payment mode. %2$s Opening anchor tag for reconnecting to Stripe, do not translate. %3$s Opening anchor tag for disconnecting Stripe, do not translate. %4$s Closing anchor tag, do not translate. */
316 __( 'Your Stripe account is connected in %1$s mode. %2$sDisconnect this account%3$s.', 'stripe' ),
317 '<strong>' . $mode . '</strong>',
318 '<a href="' . esc_url( $this->get_stripe_disconnect_url() ) . '" class="wpcharitable-disconnect-link">',
319 '</a>'
320 ) . '</p>';
321
322 $html .= '<p id="wpcharitable-stripe-unactivated-account-actions" style="display: none;"><a href="' . esc_url( $this->get_stripe_disconnect_url() ) . '">' .
323 __( 'Disconnect temporary account', 'stripe' ) .
324 '</a></p>';
325 }
326
327 return $html;
328
329 }
330
331 public function get_stripe_connect_button( $redirect_url = '' ) {
332
333 $url = $this->get_stripe_connect_url( $redirect_url );
334
335 ob_start();
336 ?>
337
338 <a href="<?php echo esc_url( $url ); ?>" aria-label="<?php echo esc_attr__( 'Connect with Stripe', 'stripe' ); ?>" class="wpcharitable-stripe-connect">
339 <span>
340 <?php
341 /* translators: Text before Stripe logo for "Connect with Stripe" button. */
342 esc_html_e( 'Connect with', 'stripe' );
343 ?>
344 </span>
345
346 <svg width="49" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.4718 10.3338c0-3.41791-1.6696-6.11484-4.8607-6.11484-3.2045 0-5.1434 2.69693-5.1434 6.08814 0 4.0187 2.289 6.048 5.5743 6.048 1.6023 0 2.8141-.3604 3.7296-.8678v-2.6702c-.9155.4539-1.9658.7343-3.2987.7343-1.3061 0-2.464-.4539-2.6121-2.0294h6.5841c0-.1735.0269-.8678.0269-1.1882Zm-6.6514-1.26838c0-1.50868.929-2.13618 1.7773-2.13618.8213 0 1.6965.6275 1.6965 2.13618h-3.4738Zm-8.5499-4.84646c-1.3195 0-2.1678.61415-2.639 1.04139l-.1751-.82777h-2.9621V20l3.3661-.7076.0134-3.7784c.4847.3471 1.1984.8411 2.3832.8411 2.4102 0 4.6048-1.9225 4.6048-6.1548-.0134-3.87186-2.235-5.98134-4.5913-5.98134Zm-.8079 9.19894c-.7944 0-1.2656-.2804-1.5888-.6275l-.0134-4.95328c.35-.38719.8348-.65421 1.6022-.65421 1.2253 0 2.0735 1.36182 2.0735 3.11079 0 1.7891-.8347 3.1242-2.0735 3.1242Zm-9.6001-9.98666 3.3796-.72096V0l-3.3796.70761v2.72363Zm0 1.01469h3.3796V16.1282h-3.3796V4.44593Zm-3.6219.98798-.2154-.98798h-2.9083V16.1282h3.3661V8.21095c.7944-1.02804 2.1408-.84112 2.5582-.69426V4.44593c-.4309-.16022-2.0062-.45394-2.8006.98798Zm-6.7322-3.88518-3.2853.69426-.01346 10.69421c0 1.976 1.49456 3.4313 3.48726 3.4313 1.1041 0 1.912-.2003 2.3563-.4406v-2.7103c-.4309.1736-2.5583.7877-2.5583-1.1882V7.28972h2.5583V4.44593h-2.5583l.0135-2.8972ZM3.40649 7.83712c0-.5207.43086-.72096 1.14447-.72096 1.0233 0 2.31588.30707 3.33917.85447V4.83311c-1.11755-.44059-2.22162-.61415-3.33917-.61415C1.81769 4.21896 0 5.63418 0 7.99733c0 3.68487 5.11647 3.09747 5.11647 4.68627 0 .6141-.53858.8144-1.29258.8144-1.11755 0-2.54477-.4539-3.675782-1.0681v3.1776c1.252192.534 2.517842.761 3.675782.761 2.80059 0 4.72599-1.3752 4.72599-3.765-.01346-3.97867-5.14339-3.27106-5.14339-4.76638Z" fill="#fff"/></svg>
347 </a>
348
349 <style>
350 .wpcharitable-stripe-connect {
351 color: #fff;
352 font-size: 15px;
353 font-weight: bold;
354 text-decoration: none;
355 line-height: 1;
356 background-color: #635bff;
357 border-radius: 3px;
358 padding: 10px 20px;
359 display: inline-flex;
360 align-items: center;
361 }
362
363 .wpcharitable-stripe-connect:focus,
364 .wpcharitable-stripe-connect:hover {
365 color: #fff;
366 background-color: #0a2540;
367 }
368
369 .wpcharitable-stripe-connect:focus {
370 outline: 0;
371 box-shadow: inset 0 0 0 1px #fff, 0 0 0 1.5px #0a2540;
372 }
373
374 .wpcharitable-stripe-connect svg {
375 margin-left: 5px;
376 }
377 </style>
378
379 <?php
380 return ob_get_clean();
381 }
382
383 public function get_stripe_connect_url( $redirect_url = '' ) {
384 if ( empty( $redirect_url ) ) {
385
386 $redirect_url = add_query_arg(
387 array(
388 'tab' => 'gateways',
389 'page' => 'charitable-settings',
390 'group' => 'gateways_stripe',
391 ),
392 admin_url( 'admin.php' )
393 );
394
395 }
396
397 return add_query_arg(
398 array(
399 'live_mode' => (int) ! charitable_get_option( 'test_mode' ), // (int) ! $this->is_test_mode(),
400 'state' => str_pad( wp_rand( wp_rand(), PHP_INT_MAX ), 100, wp_rand(), STR_PAD_BOTH ),
401 'customer_site_url' => urlencode( $redirect_url ),
402 ),
403 'https://wpcharitable.com/stripe-connect/?wpcharitable_gateway_connect_init=stripe_connect' // todo: filter market site url
404 );
405 }
406
407 public function get_stripe_disconnect_url() {
408 return add_query_arg(
409 array(
410 'wpcharitable-stripe-disconnect' => true,
411 '_wpnonce' => wp_create_nonce(
412 'wpcharitable-stripe-connect-disconnect'
413 ),
414 'tab' => 'gateways',
415 'page' => 'charitable-settings',
416 'group' => 'gateways_stripe',
417 ),
418 admin_url( 'admin.php' )
419 );
420 }
421
422 /**
423 * Returns the current gateway's ID.
424 *
425 * @return string
426 * @since 1.0.3
427 */
428 public static function get_gateway_id() {
429 return self::ID;
430 }
431
432 /**
433 * Return the keys to use.
434 *
435 * This will return the test keys if test mode is enabled. Otherwise, returns
436 * the production keys.
437 *
438 * @since 1.7.0
439 *
440 * @param boolean $force_test_mode Forces the test API keys to be used.
441 * @return string[]
442 */
443 public function get_keys( $force_test_mode = false ) {
444 $keys = [];
445
446 if ( charitable_get_option( 'test_mode' ) || $force_test_mode ) {
447 $keys['secret_key'] = trim( $this->get_value( 'test_secret_key' ) );
448 $keys['public_key'] = trim( $this->get_value( 'test_public_key' ) );
449 } else {
450 $keys['secret_key'] = trim( $this->get_value( 'live_secret_key' ) );
451 $keys['public_key'] = trim( $this->get_value( 'live_public_key' ) );
452 }
453
454 return $keys;
455 }
456
457 public function check_keys_exist( $mode ) {
458
459 $secret_key = trim( $this->get_value( $mode . '_secret_key' ) );
460 $publishable_key = trim( $this->get_value( $mode . '_public_key' ) );
461
462 if ( ! empty( $secret_key ) && ! empty( $publishable_key ) ) {
463 return true;
464 }
465
466 return false;
467 }
468
469 /**
470 * Return the submitted value for a gateway field.
471 *
472 * @since 1.7.0
473 *
474 * @param string $key The key of the value we want to get.
475 * @param mixed[] $values An values in which to search.
476 * @return string|false
477 */
478 public function get_gateway_value( $key, $values ) {
479 if ( isset( $values['gateways']['stripe'][ $key ] ) ) {
480 return $values['gateways']['stripe'][ $key ];
481 }
482
483 return false;
484 }
485
486 /**
487 * Return the submitted value for a gateway field.
488 *
489 * @since 1.7.0
490 *
491 * @param string $key The key of the value we want to get.
492 * @param Charitable_Donation_Processor $processor The Donation Processor helper object.
493 * @return string|false
494 */
495 public function get_gateway_value_from_processor( $key, Charitable_Donation_Processor $processor ) {
496 return $this->get_gateway_value( $key, $processor->get_donation_data() );
497 }
498
499 /**
500 * Add the connected account & charge owner setting to the donation form's hidden fields.
501 *
502 * @since 1.4.0
503 *
504 * @param string[] $fields The hidden fields as key=>value pairs.
505 * @param Charitable_Donation_Form $form The donation form instance.
506 * @return string[]
507 */
508 public static function add_hidden_stripe_account_field( $fields, $form ) {
509 if ( ! class_exists( 'Charitable_Stripe_Connect' ) ) {
510 return $fields;
511 }
512
513 $connected_account = charitable_stripe_get_connected_account_for_campaign( $form->get_campaign()->ID );
514
515 if ( $connected_account ) {
516 $fields['connected_account'] = $connected_account;
517 $fields['connect_charge_owner'] = charitable_get_option( [ 'gateways_stripe', 'charge_owner' ], 'direct' );
518 }
519
520 return $fields;
521 }
522
523 /**
524 * Returns an array of credit card fields.
525 *
526 * If the gateway requires different fields, this can simply be redefined
527 * in the child class.
528 *
529 * @since 1.7.0
530 *
531 * @return array[]
532 */
533 public function get_credit_card_fields() {
534 /* If Stripe Checkout is enabled, remove the credit card fields. */
535 if ( $this->get_value( 'enable_stripe_checkout' ) ) {
536 return [];
537 }
538
539 $fields = parent::get_credit_card_fields();
540
541 /* Remove all fields except for the cc_name field. */
542 unset(
543 $fields['cc_number'],
544 $fields['cc_cvc'],
545 $fields['cc_expiration']
546 );
547
548 /* Check for an existing payment intent. */
549 $intent = Charitable_Stripe_Payment_Intent::init_from_session();
550 $intent = false;
551
552 ob_start();
553
554 /**
555 * Render a template with our custom CSS. NOTE: We pass a non-empty array
556 * as the second parameter to ensure that the template is rendered immediately.
557 *
558 * @see charitable_template
559 */
560 charitable_template(
561 'stripe-elements.css.php',
562 [ 1 ],
563 'Charitable_Stripe_Template'
564 );
565 ?>
566 <label for="charitable_stripe_card_field"><?php _e( 'Credit/Debit Card', 'charitable-stripe' ); ?></label>
567 <div id="charitable_stripe_card_field" data-secret="<?php echo $intent ? $intent->get( 'client_secret' ) : ''; ?>" data-intent="<?php echo $intent ? $intent->get( 'id' ) : ''; ?>"></div>
568 <div id="charitable_stripe_card_errors" role="alert"></div>
569 <input type="hidden" name="stripe_payment_method" />
570 <?php
571
572 $fields['cc_element'] = [
573 'type' => 'content',
574 'content' => ob_get_clean(),
575 'priority' => 2,
576 ];
577
578 $fields['cc_name']['attrs'] = [
579 'data-input' => 'cc_name',
580 ];
581
582 return $fields;
583 }
584
585 /**
586 * Set up an output buffer before the donation form fields are displayed.
587 *
588 * @since 1.3.0
589 *
590 * @param Charitable_Form $form Form object.
591 * @return void
592 */
593 public static function setup_donation_form_field_output_buffer( Charitable_Form $form ) {
594 if ( 'Charitable_Donation_Form' != get_class( $form ) ) {
595 return;
596 }
597
598 ob_start();
599
600 echo '<noscript><div class="charitable-notice charitable-form-errors">
601 <ul class="charitable-notice-errors errors">
602 <li>' . __( 'For security reasons, credit card donations require Javascript. Please enable Javascript in your browser before continuing.', 'charitable-stripe' ) . '</li>
603 </ul><!-- charitable-notice- -->
604 </div></noscript>';
605 }
606
607 /**
608 * Get the donation form fields from the buffer and remove the name attribute
609 * from cc fields.
610 *
611 * @since 1.3.0
612 *
613 * @param Charitable_Form $form Form object.
614 * @return void
615 */
616 public static function remove_name_attribute_from_cc_fields( Charitable_Form $form ) {
617 if ( 'Charitable_Donation_Form' != get_class( $form ) ) {
618 return;
619 }
620
621 $fields = ob_get_clean();
622 $fields = str_replace( 'name="cc_name"', '', $fields );
623
624 echo $fields;
625 }
626
627 /**
628 * Validate the submitted credit card details.
629 *
630 * @since 1.7.0
631 * @since 1.4.0 Deprecated.
632 * @since 1.4.7 Restored. No longer deprecated.
633 *
634 * @param boolean $valid Whether the donation is valid.
635 * @param string $gateway The chosen gateway.
636 * @param mixed[] $values The filtered values from the donation form submission.
637 * @return boolean
638 */
639 public static function validate_donation( $valid, $gateway, $values ) {
640 if ( 'stripe' !== $gateway ) {
641 return $valid;
642 }
643
644 $gateway = new Charitable_Gateway_Stripe_AM();
645 $keys = $gateway->get_keys();
646
647 /* Make sure that the keys are set. */
648 if ( empty( $keys['secret_key'] ) || empty( $keys['public_key'] ) ) {
649 charitable_get_notices()->add_error( __( 'Missing keys for Stripe payment gateway. Unable to proceed with payment.', 'charitable-stripe' ) );
650 return false;
651 }
652
653 /* If we're using Payment Intents, make sure we have a payment method. */
654 if ( ! $gateway->get_value( 'enable_stripe_checkout' ) ) {
655 if ( ! array_key_exists( 'stripe_payment_method', $_POST ) || ! $_POST['stripe_payment_method'] ) {
656 charitable_get_notices()->add_error(
657 __( '<strong>Missing payment details.</strong> <a href="#charitable-gateway-fields">Click here to double-check that all required payment fields are completed.</a>', 'charitable-stripe' )
658 );
659 return false;
660 }
661 }
662
663 return $valid;
664 }
665
666 /**
667 * Checks whether the donation being processed is recurring.
668 *
669 * @since 1.3.0
670 *
671 * @param Charitable_Donation_Processor $processor The Donation Processor helper.
672 * @return boolean
673 */
674 public static function is_recurring_donation( Charitable_Donation_Processor $processor ) {
675 return $processor->get_donation_data_value( 'donation_plan', false );
676 }
677
678 /**
679 * Process the donation with the gateway, seamlessly over the Stripe API.
680 *
681 * @since 1.7.0
682 *
683 * @param mixed $return The result of the gateway processing.
684 * @param int $donation_id The donation ID.
685 * @param Charitable_Donation_Processor $processor The Donation Processor helper.
686 * @return boolean
687 */
688 public static function process_donation( $return, $donation_id, Charitable_Donation_Processor $processor ) {
689 if ( charitable_get_option( [ 'gateways_stripe', 'enable_stripe_checkout' ] ) && charitable()->is_stripe_connect_addon() ) {
690 /**
691 * Filter the processor used for handling Checkout donations.
692 *
693 * @since 1.4.0
694 *
695 * @param string $class The name of the Stripe gateway processor class.
696 * @param Charitable_Donation_Processor $processor The Donation Processor helper.
697 */
698 $processor_class = apply_filters( 'charitable_stripe_gateway_processor_checkout', 'Charitable_Stripe_Gateway_Processor_Checkout', $processor );
699 } else {
700 /**
701 * Filter the processor used for handling PaymentIntent donations.
702 *
703 * @since 1.4.0
704 *
705 * @param string $class The name of the Stripe gateway processor class.
706 * @param Charitable_Donation_Processor $processor The Donation Processor helper.
707 */
708 $processor_class = apply_filters( 'charitable_stripe_gateway_processor_payment_intents', 'Charitable_Stripe_Gateway_Processor_Payment_Intents', $processor );
709 }
710
711 $gateway_processor = new $processor_class( $donation_id, $processor );
712
713 /* Ensure we have a valid processor. */
714 if ( ! $gateway_processor instanceof Charitable_Stripe_Gateway_Processor ) {
715 $gateway_processor = new Charitable_Stripe_Gateway_Processor_Payment_Intents( $donation_id, $processor );
716 }
717
718 return $gateway_processor->run();
719 }
720
721 /**
722 * Sets up the API.
723 *
724 * This sets the API key, specifies an API version to use, and also
725 * sets the App info.
726 *
727 * @since 1.3.0
728 *
729 * @param string|null $api_key The API key. If null, will use the secret key.
730 * @return boolean
731 */
732 public function setup_api( $api_key = null ) {
733 if ( is_null( $api_key ) ) {
734 $keys = $this->get_keys();
735
736 if ( ! array_key_exists( 'secret_key', $keys ) ) {
737 return false;
738 }
739
740 $api_key = $keys['secret_key'];
741 }
742
743 /**
744 * On certain versions of CentOS, curl requests to Stripe fail consistently.
745 * The following filter provides a way to work around this with the following:
746 *
747 add_filter( 'charitable_stripe_http_curl_client', function( \Stripe\HttpClient\CurlClient $curl ) {
748 $curl->setEnablePersistentConnections( false );
749 return $curl;
750 } );
751 *
752 * @see https://github.com/stripe/stripe-php/issues/918
753 *
754 * @since 1.4.11
755 *
756 * @param \Stripe\HttpClient\CurlClient $curl The CurlClient instance.
757 */
758 $curl = apply_filters( 'charitable_stripe_http_curl_client', new \Stripe\HttpClient\CurlClient() );
759
760 /* Allow the Curl client object to be changed. */
761 \Stripe\ApiRequestor::setHttpClient( $curl );
762
763 \Stripe\Stripe::setApiKey( $api_key );
764 \Stripe\Stripe::setApiVersion( Charitable_Gateway_Stripe_AM::STRIPE_API_VERSION );
765 \Stripe\Stripe::setAppInfo(
766 'WordPress CharitablePlugin',
767 charitable_stripe()->get_version(),
768 'https://www.wpcharitable.com',
769 'pp_partner_Ee8qdpxEQjiEne'
770 );
771
772 return true;
773 }
774
775 /**
776 * Check whether a particular donation can be refunded automatically in Stripe.
777 *
778 * @since 1.3.0
779 *
780 * @param Charitable_Donation $donation The donation object.
781 * @return boolean
782 */
783 public function is_donation_refundable( Charitable_Donation $donation ) {
784 $secret_key = $donation->get_test_mode( false ) ? 'test_secret_key' : 'live_secret_key';
785
786 if ( ! $this->get_value( $secret_key ) ) {
787 return false;
788 }
789
790 //todo: determine why this function might not be available when this is called on the donation detail page.
791 if ( function_exists( 'charitable_stripe_get_charge_id_for_donation' ) ) {
792 return false !== charitable_stripe_get_charge_id_for_donation( $donation->ID );
793 } else {
794 return false;
795 }
796
797 }
798
799 /**
800 * Process a refund initiated in the WordPress dashboard.
801 *
802 * @since 1.3.0
803 *
804 * @param int $donation_id The donation ID.
805 * @return boolean
806 */
807 public static function refund_donation_from_dashboard( $donation_id ) {
808 $donation = charitable_get_donation( $donation_id );
809
810 if ( ! $donation ) {
811 return false;
812 }
813
814 $charge = charitable_stripe_get_charge_id_for_donation( $donation_id );
815
816 if ( ! $charge ) {
817 return false;
818 }
819
820 $gateway = new Charitable_Gateway_Stripe_AM();
821 $key = $donation->get_test_mode( false ) ? 'test_secret_key' : 'live_secret_key';
822 $api_key = $gateway->get_value( $key );
823 $account = charitable_stripe_get_account_id_for_donation( $donation->ID );
824 $options = $account ? [ 'stripe_account' => $account ] : null;
825
826 if ( ! $api_key ) {
827 return false;
828 }
829
830 $gateway->setup_api( $api_key );
831
832 $data = 0 === strpos( $charge, 'pi_' ) ? [ 'payment_intent' => $charge ] : [ 'charge' => $charge ];
833
834 try {
835 $refund = \Stripe\Refund::create( $data, $options );
836
837 update_post_meta( $donation_id, '_stripe_refunded', true );
838 update_post_meta( $donation_id, '_stripe_refund_id', $refund->id );
839
840 $donation->log()->add(
841 sprintf(
842 /* translators: %s: transaction reference. */
843 __( 'Stripe refund transaction ID: %s', 'charitable-stripe' ),
844 $refund->id
845 )
846 );
847
848 return true;
849 } catch ( \Stripe\Error\InvalidRequest $e ) {
850 $donation->log()->add(
851 sprintf(
852 /* translators: %s: error message. */
853 __( 'Stripe refund failed: %s', 'charitable-stripe' ),
854 $e->getStripeCode()
855 )
856 );
857 return false;
858 }
859 }
860
861 /**
862 * Check whether a recurring donation can be cancelled automatically in Stripe.
863 *
864 * @since 1.3.0
865 *
866 * @param boolean $can_cancel Whether the subscription can be cancelled.
867 * @param Charitable_Recurring_Donation $donation The donation object.
868 * @return boolean
869 */
870 public static function is_subscription_cancellable( $can_cancel, Charitable_Recurring_Donation $donation ) {
871 if ( ! $can_cancel ) {
872 return $can_cancel;
873 }
874
875 $secret_key = $donation->get_test_mode( false ) ? 'test_secret_key' : 'live_secret_key';
876
877 if ( ! charitable_get_option( [ 'gateways_stripe', $secret_key ] ) ) {
878 return false;
879 }
880
881 return ! empty( $donation->get_gateway_subscription_id() );
882 }
883
884 /**
885 * Cancel a subscription.
886 *
887 * This can be triggered via the WordPress dashboard when editing a recurring
888 * donation, or via the user's own account area.
889 *
890 * @since 1.3.0
891 *
892 * @param boolean $cancelled Whether the subscription was cancelled successfully in the gateway.
893 * @param Charitable_Recurring_Donation $donation The recurring donation object.
894 * @return boolean
895 */
896 public static function cancel_subscription( $cancelled, Charitable_Recurring_Donation $donation ) {
897 $subscription_id = $donation->get_gateway_subscription_id();
898
899 if ( ! $subscription_id ) {
900 return false;
901 }
902
903 $gateway = new Charitable_Gateway_Stripe_AM();
904 $key = $donation->get_test_mode( false ) ? 'test_secret_key' : 'live_secret_key';
905 $api_key = $gateway->get_value( $key );
906 $account = charitable_stripe_get_account_id_for_donation( $donation->ID );
907 $options = $account ? [ 'stripe_account' => $account ] : null;
908
909 if ( ! $api_key ) {
910 return false;
911 }
912
913 $gateway->setup_api( $api_key );
914
915 try {
916 $subscription = \Stripe\Subscription::retrieve( $subscription_id, $options );
917 $subscription->cancel( null, $options );
918
919 $donation->log()->add( __( 'Subscription cancelled in Stripe.', 'charitable-stripe' ) );
920
921 $cancelled = true;
922
923 } catch ( Exception $e ) {
924 $body = $e->getJsonBody();
925 $message = isset( $body['error']['message'] ) ? $body['error']['message'] : __( 'Unknown error.', 'charitable-stripe' );
926
927 $donation->log()->add(
928 sprintf(
929 /* translators: %s: error message */
930 __( 'Stripe cancellation failed: %s', 'charitable-stripe' ),
931 $message
932 )
933 );
934
935 $cancelled = false;
936
937 } finally {
938 return $cancelled;
939 }
940 }
941
942 /**
943 * Cancel a subscription in Stripe after the recurring donation is marked as completed.
944 *
945 * @since 1.4.9
946 *
947 * @param Charitable_Recurring_Donation $donation The recurring donation object.
948 * @return boolean
949 */
950 public function process_completed_subscription( $recurring_donation ) {
951 return self::cancel_subscription( true, $recurring_donation );
952 }
953
954 /**
955 * Get the donation amount in the smallest common currency unit.
956 *
957 * @since 1.2.3
958 *
959 * @param float $amount The donation amount in dollars.
960 * @param string|null $currency The currency of the donation. If null, the site currency will be used.
961 * @return int
962 */
963 public static function get_amount( $amount, $currency = null ) {
964 return Charitable_Stripe_Gateway_Processor::get_sanitized_donation_amount( $amount, $currency );
965 }
966
967 /**
968 * Returns whether the currency is a zero decimal currency.
969 *
970 * @since 1.2.3
971 *
972 * @param string $currency The currency for the charge. If left blank, will check for the site currency.
973 * @return boolean
974 */
975 public static function is_zero_decimal_currency( $currency = null ) {
976 return Charitable_Stripe_Gateway_Processor::is_zero_decimal_currency( $currency );
977 }
978
979 /**
980 * Return all zero-decimal currencies supported by Stripe.
981 *
982 * @since 1.2.3
983 *
984 * @return array
985 */
986 public static function get_zero_decimal_currencies() {
987 return Charitable_Stripe_Gateway_Processor::get_zero_decimal_currencies();
988 }
989
990 /**
991 * Attemps a Stripe charge and returns the status of the charge.
992 *
993 * @deprecated 1.5.0 To be removed in 1.5.0.
994 *
995 * @since 1.1.0
996 * @since 1.3.0 Deprecated.
997 *
998 * @param array $charge_args The arguments for the charge API request.
999 * @param Charitable_Donor $donor The current user.
1000 * @param Charitable_Donation_Processor $processor The Donation Processor helper object.
1001 * @return string
1002 */
1003 public function make_charge( $charge_args, $donor, $processor ) {
1004 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1005 }
1006
1007 /**
1008 * Set the $charges property to empty.
1009 *
1010 * @deprecated 1.5.0 To be removed in 1.5.0.
1011 *
1012 * @since 1.1.0
1013 * @since 1.3.0 Deprecated.
1014 *
1015 * @return void
1016 */
1017 public function clear_charges() {
1018 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1019 }
1020
1021 /**
1022 * Return the results of all charges.
1023 *
1024 * @deprecated 1.5.0 To be removed in 1.5.0.
1025 *
1026 * @since 1.1.0
1027 * @since 1.3.0 Deprecated.
1028 *
1029 * @return array
1030 */
1031 public function get_charges() {
1032 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1033 }
1034
1035 /**
1036 * Saves the results of a charge.
1037 *
1038 * @deprecated 1.5.0 To be removed in 1.5.0.
1039 *
1040 * @since 1.1.0
1041 * @since 1.3.0 Deprecated.
1042 *
1043 * @return void
1044 */
1045 public function save_charge_results( $result, $status ) {
1046 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1047 }
1048
1049 /**
1050 * Returns a card ID for the customer.
1051 *
1052 * @deprecated 1.5.0 To be removed in 1.5.0.
1053 *
1054 * @since 1.7.0
1055 * @since 1.3.0 Deprecated.
1056 *
1057 * @param string $customer Stripe's customer ID.
1058 * @param string $card The customer's card details or token.
1059 * @return string|false Card ID or false if Stripe returns an error.
1060 */
1061 public function get_customer_card( $customer, $card ) {
1062 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1063
1064 try {
1065
1066 $cu = \Stripe\Customer::retrieve( $customer );
1067 $card = $cu->sources->create( [ 'source' => $card ] );
1068 $card_id = $card->id;
1069
1070 } catch ( Exception $e ) {
1071
1072 $body = $e->getJsonBody();
1073 $message = isset( $body['error']['message'] ) ? $body['error']['message'] : __( 'Something went wrong.', 'charitable-stripe' );
1074 charitable_get_notices()->add_error( $message );
1075 $card_id = false;
1076
1077 }
1078
1079 return $card_id;
1080 }
1081
1082 /**
1083 * Return the Stripe Customer ID for the current customer.
1084 *
1085 * If the donor has donated previously through Stripe, this will return
1086 * their ID from the database. If not, this will first set them up as a
1087 * customer in Stripe, store their customer ID and then return it.
1088 *
1089 * @deprecated 1.5.0 To be removed in 1.5.0.
1090 *
1091 * @since 1.7.0
1092 * @since 1.3.0 Deprecated.
1093 *
1094 * @param Charitable_User|Charitable_Donor $donor The donor/user object for the logged in user.
1095 * @param Charitable_Donation_Processor $processor The Donation Procesor helper.
1096 * @return string|false
1097 */
1098 public function get_stripe_customer( $donor, Charitable_Donation_Processor $processor ) {
1099 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1100
1101 $key = charitable_get_option( 'test_mode' ) ? self::STRIPE_CUSTOMER_ID_KEY_TEST : self::STRIPE_CUSTOMER_ID_KEY;
1102
1103 /**
1104 * Retrieve current customer ID and verify that the customer still exists
1105 * in Stripe.
1106 */
1107 $stripe_customer_id = $donor->$key;
1108
1109 if ( $stripe_customer_id ) {
1110
1111 try {
1112 /* Retrieve the customer object from Stripe. */
1113 $cu = \Stripe\Customer::retrieve( $stripe_customer_id );
1114
1115 } catch ( Stripe\Error\InvalidRequest $e ) {
1116 $cu = null;
1117 }
1118
1119 if ( is_null( $cu ) || ( isset( $cu->deleted ) && $cu->deleted ) ) {
1120 $stripe_customer_id = false;
1121 }
1122 }
1123
1124 /* No Stripe Customer ID found, so we're going to create one. */
1125 if ( ! $stripe_customer_id ) {
1126
1127 $stripe_customer_id = $this->create_stripe_customer( $donor, $processor );
1128
1129 /* Store the customer ID for logged in users. */
1130 if ( $stripe_customer_id && $donor->ID ) {
1131 update_user_meta( $donor->ID, $key, $stripe_customer_id );
1132 }
1133 }
1134
1135 return $stripe_customer_id;
1136 }
1137
1138 /**
1139 * Create a Stripe Customer object through the API.
1140 *
1141 * @deprecated 1.5.0 To be removed in 1.5.0 or 2.0.0.
1142 *
1143 * @since 1.2.2
1144 * @since 1.3.0 Deprecated.
1145 *
1146 * @param Charitable_Donor $donor The Donor object.
1147 * @param Charitable_Donation_Processor $processor The Donation Procesor helper.
1148 * @return string|false
1149 */
1150 public function create_stripe_customer( $donor, Charitable_Donation_Processor $processor ) {
1151 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1152
1153 $stripe_customer_args = apply_filters(
1154 'charitable_stripe_customer_args',
1155 array(
1156 'description' => sprintf( '%s %s', __( 'Donor for', 'charitable-stripe' ), $donor->get_email() ),
1157 'email' => $donor->get_email(),
1158 'metadata' => array(
1159 'donor_id' => $processor->get_donor_id(),
1160 'user_id' => $donor->ID,
1161 ),
1162 ),
1163 $donor,
1164 $processor
1165 );
1166
1167 try {
1168 $customer = \Stripe\Customer::create( $stripe_customer_args );
1169
1170 return $customer->id;
1171
1172 } catch ( Exception $e ) {
1173 $body = $e->getJsonBody();
1174 $message = isset( $body['error']['message'] ) ? $body['error']['message'] : __( 'Something went wrong.', 'charitable-stripe' );
1175 charitable_get_notices()->add_error( $message );
1176
1177 return false;
1178 }
1179 }
1180
1181 /**
1182 * Returns the payment source.
1183 *
1184 * This may return a string, identifying the ID of a payment source such as
1185 * a credit card. It may also be an associative array containing the user's
1186 * credit card details.
1187 *
1188 * @deprecated 1.5.0 To be removed in 1.5.0.
1189 *
1190 * @since 1.7.0
1191 * @since 1.3.0 Deprecated.
1192 *
1193 * @param Charitable_User|Charitable_Donor $donor The donor/user object for the logged in user.
1194 * @param Charitable_Donation_Processor $processor The Donation Procesor helper.
1195 * @return string|array
1196 */
1197 public function get_source( $donor, Charitable_Donation_Processor $processor ) {
1198 charitable_stripe_get_deprecated()->deprecated_function( __METHOD__, '1.3.0' );
1199
1200 $values = $processor->get_donation_data();
1201
1202 /**
1203 * If the donation is made by a logged in user who selected
1204 * a source (card), return that.
1205 */
1206 if ( $this->get_gateway_value( 'source', $values ) ) {
1207 return $this->get_gateway_value( 'source', $values );
1208 }
1209
1210 /**
1211 * If we have a token available, return that.
1212 */
1213 if ( $this->get_gateway_value( 'token', $values ) ) {
1214 return $this->get_gateway_value( 'token', $values );
1215 }
1216
1217 charitable_get_notices()->add_error( __( 'Missing credit card details. Unable to proceed with payment.', 'charitable-stripe' ) );
1218
1219 return false;
1220 }
1221
1222 /**
1223 * Load Stripe JS, as well as our handling scripts.
1224 *
1225 * @deprecated 1.6.0
1226 *
1227 * @since 1.1.0
1228 * @since 1.4.0 Deprecated. Method moved to Charitable_Stripe class.
1229 *
1230 * @return boolean
1231 */
1232 public static function enqueue_scripts() {
1233 charitable_stripe_get_deprecated()->deprecated_function(
1234 __METHOD__,
1235 '1.4.0',
1236 'charitable_stripe()->enqueue_scripts()'
1237 );
1238
1239 return charitable_stripe()->enqueue_scripts();
1240 }
1241
1242 /**
1243 * Load Stripe JS or Stripe Checkout, as well as our handling scripts.
1244 *
1245 * @deprecated 1.6.0
1246 *
1247 * @since 1.1.2
1248 * @since 1.4.0 Deprecated. Method moved to Charitable_Stripe class.
1249 *
1250 * @param Charitable_Donation_Form $form The current form object.
1251 * @return boolean
1252 */
1253 public static function maybe_setup_scripts_in_donation_form( $form ) {
1254 charitable_stripe_get_deprecated()->deprecated_function(
1255 __METHOD__,
1256 '1.4.0',
1257 'charitable_stripe()->maybe_setup_scripts_in_donation_form( $form )'
1258 );
1259
1260 return charitable_stripe()->maybe_setup_scripts_in_donation_form( $form );
1261 }
1262
1263 /**
1264 * Enqueue the Stripe JS/Checkout scripts after a campaign loop if modal donations are in use.
1265 *
1266 * @deprecated 1.6.0
1267 *
1268 * @since 1.1.2
1269 * @since 1.4.0 Deprecated. Method moved to Charitable_Stripe class.
1270 *
1271 * @return boolean
1272 */
1273 public static function maybe_setup_scripts_in_campaign_loop() {
1274 charitable_stripe_get_deprecated()->deprecated_function(
1275 __METHOD__,
1276 '1.4.0',
1277 'charitable_stripe()->maybe_setup_scripts_in_campaign_loop()'
1278 );
1279
1280 return charitable_stripe()->maybe_setup_scripts_in_campaign_loop();
1281 }
1282
1283
1284 /**
1285 * Checks if credit card details are required.
1286 *
1287 * Credit card details are required UNLESS the donation is being
1288 * made by a logged in user who has donated before and is using
1289 * one of their stored cards (stored on Stripe's server, not ours).
1290 *
1291 * @deprecated 1.6.0
1292 *
1293 * @since 1.7.0
1294 * @since 1.4.0 Deprecated.
1295 *
1296 * @param array $values The filtered values from the donation form submission.
1297 * @return boolean
1298 */
1299 public function require_credit_card_details( $values ) {
1300 charitable_stripe_get_deprecated()->deprecated_function(
1301 __METHOD__,
1302 '1.4.0'
1303 );
1304
1305 return false;
1306 }
1307
1308 /**
1309 * Determine if the Stripe addon should be shown on the frontend if no keys are found
1310 *
1311 * @param array[] $gateways The list of registered gateways.
1312 * @return string[]
1313 * @since 1.7.0
1314 */
1315 public function maybe_active_public_gateway( $active_gateways ) {
1316
1317 if ( ! isset( $active_gateways['stripe'] ) ) {
1318 return $active_gateways;
1319 }
1320
1321 if ( is_admin() ) {
1322 // if this is the admin backend don't mess with this list.
1323 return $active_gateways;
1324 }
1325
1326 global $post;
1327
1328 if ( false === $post || ! isset( $post->ID ) ) {
1329 return $active_gateways;
1330 }
1331
1332 // ok, this is being loaded as an active gateway - but do we have any keys?
1333 $keys = $this->get_keys();
1334
1335 /* Make sure that the keys are set, otherwise there will likely be JS error in the template that will effect other JS generated by the plugin on the page. */
1336 if ( empty( $keys['secret_key'] ) || empty( $keys['public_key'] ) ) {
1337 charitable_get_notices()->add_error( __( 'Missing keys for Stripe payment gateway. Unable to proceed with payment.', 'charitable-stripe' ) );
1338 unset( $active_gateways['stripe'] );
1339 }
1340
1341 return $active_gateways;
1342
1343 }
1344
1345 /**
1346 * Register the Stripe payment gateway class.
1347 *
1348 * @param string $settings Setting, which might have been stored in the database by an addon.
1349 * @param string $original_key Oringial key.
1350 * @param string $default Default setting.
1351 * @return string
1352 * @since 1.7.0
1353 */
1354 public function maybe_return_stripe_connect_setting( $setting, $original_key, $default ) {
1355
1356 if ( ! charitable()->is_stripe_connect_addon() ) {
1357 // if the stripe connect addon isn't activated, then this setting shouldn't be retreavable (although it stays in the dataabase).
1358 $setting = null;
1359 }
1360
1361 return $setting;
1362 }
1363
1364
1365 /**
1366 * Stripe shows errors for amounts less tha $1, so set the min. amount to 1. This filter catches the ajax request.
1367 *
1368 * @return integer
1369 * @since 1.7.0.2
1370 */
1371 public function set_minimum_donation_amount( $minimum_amount ) {
1372
1373 if ( isset( $_POST['gateway'] ) && false !== strpos( $_POST['gateway'], 'stripe' ) ) {
1374 // Stripe gateway detected - make sure the minimum aount is at least 1 (logic revised in 1.7.0.9)
1375 if ( intval( $minimum_amount ) < 1 ) {
1376 $minimum_amount = 1;
1377 }
1378 }
1379
1380 return $minimum_amount;
1381
1382 }
1383
1384 /**
1385 * Use existing pre-1.7.0 hook to process webhooks that are for Stripe Connect AM accounts.
1386 *
1387 * @since 1.7.0
1388 */
1389 public function maybe_process_webhook_with_stripe_connect( $event_type, $event ) {
1390
1391 // a reminder on this check:
1392 // the option gets written when the stripe connect in the core plugin (starting in v1.7.0) is connected in gateway settings in the admin.
1393 // the option is removed when, after the stripe connect is connected, the user clicks on the "disconnect" link is clicked in the settings.
1394 if ( ! charitable_using_stripe_connect() ) {
1395 return;
1396 }
1397
1398 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
1399 error_log( 'maybe_process_webhook_with_stripe_connect' );
1400 error_log( print_r( $event_type, true ) );
1401 error_log( print_r( $event, true ) );
1402 }
1403
1404 $processor = new Charitable_Stripe_Webhook_Processor( $event );
1405
1406 $default_processors = apply_filters(
1407 'charitable_stripe_default_event_processors',
1408 [
1409 'charge.refunded' => [ $processor, 'process_refund' ],
1410 'invoice.created' => [ $processor, 'process_invoice_created' ],
1411 'invoice.payment_failed' => [ $processor, 'process_invoice_payment_failed' ],
1412 'invoice.payment_succeeded' => [ $processor, 'process_invoice_payment_succeeded' ],
1413 'customer.subscription.updated' => [ $processor, 'process_customer_subscription_updated' ],
1414 'customer.subscription.deleted' => [ $processor, 'process_customer_subscription_deleted' ],
1415 'payment_intent.payment_failed' => [ $processor, 'process_payment_intent_payment_failed' ],
1416 'payment_intent.succeeded' => [ $processor, 'process_payment_intent_succeeded' ],
1417 'checkout.session.completed' => [ $processor, 'process_checkout_session_completed' ],
1418 ]
1419 );
1420
1421 if ( array_key_exists( $event_type, $default_processors ) ) {
1422 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
1423 error_log( 'message start');
1424 }
1425 $message = call_user_func( $default_processors[ $event_type ], $event );
1426 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
1427 error_log( print_r( $message, true ) );
1428 error_log( 'message stop');
1429 }
1430 /* Kill processing with a message returned by the event processor. */
1431 die( $message );
1432 }
1433
1434
1435
1436
1437 }
1438
1439 }
1440
1441 endif;
1442