PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.6
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.6
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.6, at includes/gateways/class-charitable-gateway-stripe-am.php

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