Created
July 29, 2026 11:54
-
-
Save xlplugins/302ae514c0b318acef5859009783fffb to your computer and use it in GitHub Desktop.
FunnelKit Stripe — Webhook Health Admin Notice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Plugin Name: FunnelKit Stripe — Webhook Health Admin Notice | |
| * Description: Shows a WordPress admin notice when the Stripe webhook appears broken: | |
| * (a) the last webhook delivery failed, (b) a webhook is configured but has | |
| * been silent for over a day, or (c) the live webhook endpoint in Stripe is | |
| * missing / disabled / pointing to a different URL — verified through the | |
| * plugin's own fkwcs_check_live_webhook_url ajax, throttled to every 12h. | |
| * The notice clears automatically once the webhook works again. | |
| */ | |
| defined( 'ABSPATH' ) || exit; | |
| const FKWCS_WHN_PROBE_RESULT = 'fkwcs_whn_probe_result'; // option: '' = ok, string = problem found by probe | |
| const FKWCS_WHN_PROBE_LOCK = 'fkwcs_whn_probe_lock'; // transient: probe throttle | |
| /** | |
| * 1) The admin notice — combines the plugin's passive webhook-health options with the | |
| * last active probe result. | |
| */ | |
| add_action( 'admin_notices', function () { | |
| if ( ! defined( 'FKWCS_VERSION' ) || ! current_user_can( 'manage_woocommerce' ) ) { | |
| return; | |
| } | |
| $mode = ( 'test' === get_option( 'fkwcs_mode', 'test' ) ) ? 'test' : 'live'; | |
| $success = (int) get_option( "fkwcs_{$mode}_webhook_last_success_at" ); | |
| $failure = (int) get_option( "fkwcs_{$mode}_webhook_last_failure_at" ); | |
| $began = (int) get_option( "fkwcs_{$mode}_webhook_began_at" ); | |
| $error = get_option( "fkwcs_{$mode}_webhook_last_error" ); | |
| $problems = array(); | |
| if ( $failure && $failure >= $success ) { | |
| $problems[] = sprintf( | |
| 'The last Stripe webhook call failed %1$s ago.%2$s', | |
| human_time_diff( $failure ), | |
| $error ? ' Error: <b>' . esc_html( $error ) . '</b>.' : '' | |
| ); | |
| } elseif ( ! $success && $began && ( time() - $began ) > DAY_IN_SECONDS ) { | |
| $problems[] = sprintf( | |
| 'No Stripe webhook has been received for %s, although a webhook secret is configured.', | |
| human_time_diff( $began ) | |
| ); | |
| } | |
| $probe = get_option( FKWCS_WHN_PROBE_RESULT, '' ); | |
| if ( '' !== $probe && is_string( $probe ) ) { | |
| $problems[] = esc_html( $probe ); | |
| } | |
| if ( empty( $problems ) ) { | |
| return; | |
| } | |
| printf( | |
| '<div class="notice notice-error"><p><b>%s</b> %s %s <a href="%s">%s</a></p></div>', | |
| 'FunnelKit Stripe webhook problem:', | |
| wp_kses_post( implode( ' ', $problems ) ), | |
| 'Payments may succeed in Stripe without the WooCommerce order updating.', | |
| esc_url( admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings' ) ), | |
| 'Review webhook settings →' | |
| ); | |
| } ); | |
| /** | |
| * 2) Active probe using the plugin's own fkwcs_check_live_webhook_url ajax. | |
| * Runs at most every 12h — except on FunnelKit Stripe settings screens, where it always | |
| * runs so a repaired webhook clears the notice immediately. | |
| */ | |
| add_action( 'admin_footer', function () { | |
| if ( ! defined( 'FKWCS_VERSION' ) || ! current_user_can( 'manage_woocommerce' ) ) { | |
| return; | |
| } | |
| $is_stripe_screen = isset( $_GET['tab'] ) && false !== strpos( sanitize_text_field( wp_unslash( $_GET['tab'] ) ), 'fkwcs' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| if ( ! $is_stripe_screen && get_transient( FKWCS_WHN_PROBE_LOCK ) ) { | |
| return; | |
| } | |
| $check_nonce = wp_create_nonce( 'fkwcs_admin_request' ); | |
| $save_nonce = wp_create_nonce( 'fkwcs_whn_save' ); | |
| ?> | |
| <script id="fkwcs-whn-probe"> | |
| (function () { | |
| var url = window.ajaxurl || '<?php echo esc_js( admin_url( 'admin-ajax.php' ) ); ?>'; | |
| function save(problem) { | |
| var d = new FormData(); | |
| d.append('action', 'fkwcs_whn_save_probe'); | |
| d.append('_security', '<?php echo esc_js( $save_nonce ); ?>'); | |
| d.append('problem', problem); | |
| fetch(url, { method: 'POST', credentials: 'same-origin', body: d }); | |
| } | |
| var f = new FormData(); | |
| f.append('action', 'fkwcs_check_live_webhook_url'); | |
| f.append('_security', '<?php echo esc_js( $check_nonce ); ?>'); | |
| fetch(url, { method: 'POST', credentials: 'same-origin', body: f }) | |
| .then(function (r) { return r.json(); }) | |
| .then(function (res) { | |
| var d = (res && res.data) || {}; | |
| if (d.mismatch === true) { | |
| save(d.actual_url | |
| ? 'The Stripe webhook endpoint does not point to this site (or is disabled) — endpoint found: ' + d.actual_url | |
| : 'The Stripe webhook endpoint could not be found in your Stripe account' + (d.msg ? ' (' + d.msg + ')' : '') + '.'); | |
| } else { | |
| save(''); // healthy or not verifiable — clear any previous probe alarm | |
| } | |
| }) | |
| .catch(function () { /* network hiccup — keep previous state */ }); | |
| })(); | |
| </script> | |
| <?php | |
| } ); | |
| /** | |
| * 3) Store the probe result. Empty string clears the alarm; sets the 12h throttle. | |
| */ | |
| add_action( 'wp_ajax_fkwcs_whn_save_probe', function () { | |
| check_ajax_referer( 'fkwcs_whn_save', '_security' ); | |
| if ( ! current_user_can( 'manage_woocommerce' ) ) { | |
| wp_send_json_error(); | |
| } | |
| $problem = isset( $_POST['problem'] ) ? sanitize_text_field( wp_unslash( $_POST['problem'] ) ) : ''; | |
| update_option( FKWCS_WHN_PROBE_RESULT, $problem, false ); | |
| set_transient( FKWCS_WHN_PROBE_LOCK, 1, 12 * HOUR_IN_SECONDS ); | |
| wp_die(); | |
| } ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment